• | Table of Contents
• | Index
Macromedia® Flash™ Communication Server MX
By Kevin Towes
Publisher | : New Riders Publishing
Pub Date | : December 12, 2002
ISBN | : 0-7357-1333-2
Pages | : 504

Flash Communicator Server MX is your complete guide to integrating rich media and real-time collaboration into your applications with Flash Communication Server MX! It includes 10 quick steps for getting started and covers ActionScripting, Flash Remoting, and other key implementation issues from a server-side perspective. It provides excellent tutorials for creating usable, media rich applications that allow real-time collaboration.

There is much to learn in order to harness the true power of the Flash Communication Server MX. Macromedia's new server integrates support for streaming media, multi-way video, audio and text messaging, and real-time collaboration into a single solution. Flash Communication Server MX is an introduction to the technology, as well a guide to implementation of successful applications. Part I provides 10 quick steps to get you familiar with the server and how it works. Part II explores the important issues affecting appropriate integration of the Communication Server. Key concepts include understanding digital communication solutions, understanding objects, using server side ActionScripting, Flash Remoting, and security issues. A third section provides tutorials on how to create some popular applications for the server. Finally, a series of appendices supply reference material for Flash Communication Server MX users.


• | Table of Contents
• | Index
Macromedia® Flash™ Communication Server MX
By Kevin Towes
Publisher | : New Riders Publishing
Pub Date | : December 12, 2002
ISBN | : 0-7357-1333-2
Pages | : 504

Copyright
About the Author
About Pangaea NewMedia, Inc.
About NI Solutions Group, Inc.
About the Technical Reviewers
Acknowledgments
Tell Us What You Think
Foreword
Preface
 | Exactly What Is Macromedia Flash Communication Server MX?
 | Why Is Flash Communication Server Needed?
 | Who Is This Book for?
 | What Does the Book Cover?
 | What Are the Software Requirements?
 | Trial Software and Downloads
 | What Is on the Web Site?
Part I: 10 Quick Steps for Getting Started
 | Chapter 1. STEP 1: Installation and Setup
 |  | Installation and Setup
 |  | The Personal Edition
 |  | The Professional Edition
 |  | Before You Install
 |  | Ports
 |  | Installation
 |  | Macromedia Flash MX Components
 |  | After the Server Installation
 |  | Summary
 | Chapter 2. STEP 2: Your Development Environment
 |  | The Server Files
 |  | Servers and Access
 |  | The Authoring Environment: Macromedia Flash MX
 |  | The Testing Environment
 |  | Summary
 | Chapter 3. STEP 3: Get Connected
 |  | Define Your Application on the Server
 |  | Build the User Interface in Macromedia Flash MX
 |  | Testing the Movie
 |  | What to Check if Your Application Is Not Working
 |  | Summary
 | Chapter 4. STEP 4: Simple Chat and Video Conferencing
 |  | The Chat and UserColor Communication UI Components
 |  | The AVPresence Communication UI Component
 |  | The SetBandwidth Communication UI Component
 |  | Summary
 | Chapter 5. STEP 5: Monitoring and Managing the Server
 |  | What Happens When You Run Your Flash Communication Server MX Application?
 |  | ADMIN Component: Administration Console
 |  | Developer Component: Communication App Inspector
 |  | Developer Component: NetConnection Debugger
 |  | Summary
 | Chapter 6. STEP 6: ActionScript with NetConnection()
 |  | The ActionScript Editor—a Primer
 |  | The NetConnection() Object
 |  | NetConnection() Methods, Properties, and Events
 |  | Summary
 | Chapter 7. STEP 7: Streaming Video with NetStream()
 |  | Overview
 |  | Streaming Video and Bandwidth
 |  | The NetStream() Object, Methods, Properties, and Event
 |  | Playing Live Video
 |  | Summary
 | Chapter 8. STEP 8: Collaboration with SharedObject()
 |  | SharedObject Methods
 |  | SharedObject Property
 |  | SharedObject Events
 |  | How Does the Shared Cursor Work?
 |  | Synchronization
 |  | Implementing SharedObjects
 |  | Data Management Using Slots
 |  | Summary
 | Chapter 9. STEP 9: Controller and Subscriber Applications
 |  | Controller Applications
 |  | Chapter Project Overview
 |  | Testing the Project
 |  | The Presentation File (simple_preso.swf)
 |  | Summary
 | Chapter 10. STEP 10: Lobby Applications
 |  | Lobby Application Overview
 |  | Chapter Exercises Overview
 |  | Summary
Part II: Implementing Macromedia Flash Communication Server
 | Chapter 11. Server-Side ActionScript (SSAS)
 |  | The main.asc File
 |  | Application Instances
 |  | Components and the ScriptLib Folder
 |  | Server-Side Objects
 |  | Debugging Techniques
 |  | Summary
 | Chapter 12. Client-Side (Flash) ActionScript
 |  | Macromedia Flash MX Communication Tools
 |  | The Communication ActionScript Objects
 |  | The Macromedia Flash Communication UI Components
 |  | Code Hinting
 |  | Debugging Techniques
 |  | Summary
 | Chapter 13. Accessing External Data
 |  | Macromedia Flash Remoting MX
 |  | NetServices in Macromedia Flash MX
 |  | NetServices on the Macromedia Flash Communication Server
 |  | Project: Using Remoting to Authenticate a User
 |  | Summary
 | Chapter 14. Server Administration
 |  | The Server Structure
 |  | The Server
 |  | The Adaptor
 |  | The Virtual Host
 |  | The Application
 |  | Creating Multiple Adaptors and Virtual Hosts
 |  | Summary
 | Chapter 15. Communication Application Architecture Strategies
 |  | What Does What When?
 |  | Handling Connection Failures
 |  | Security
 |  | ActionScript Techniques
 |  | Server Management API
 |  | Additional Resources
 |  | Summary
Part III: Tutorials
 | Chapter 16. Build a Technical Support Application
 |  | Live Support Lobby Application
 |  | Live Support Session Application
 |  | Summary
 | Chapter 17. Making Faces: The Living Emoticon
 |  | The User Perspective
 |  | Putting Macromedia Flash MX in Developer Mode
 |  | The Interface
 |  | Macromedia Flash ActionScript (Frame 1)
 |  | Summary
 | Chapter 18. Build Training and Education: The Virtual Classroom
 |  | Student User Case Study
 |  | Teacher User Case Study
 |  | The Interfaces
 |  | The Code
 |  | Summary
Appendix IV. Appendixes: Quick Reference Guides
 | Appendix A. Server-Side Objects Quick Reference
 |  | Application Object
 |  | Client Object
 |  | NetConnection Object
 |  | NetServices Object (Macromedia Flash Remoting MX)
 |  | RecordSet Object
 |  | SharedObject Object
 |  | Stream Object
 | Appendix B. Macromedia Flash ActionScript Objects Quick Reference
 |  | Camera Object
 |  | Microphone Object
 |  | NetConnection Object
 |  | NetServices Object
 |  | NetStream Object
 |  | RecordSet Object
 |  | SharedObject Object
 |  | Video Object
 | Appendix C. Information Objects (Server and Client) Quick Reference
 | Appendix D. Macromedia Flash UI Component Objects Quick Reference
 |  | Common Methods
 |  | Lurker Mode
 |  | Macromedia Flash UI Component ActionScript Objects
 | Appendix E. Useful ActionScript Templates Quick Reference
 |  | Checklist for Creating a New Application
 |  | ActionScript Connect and Connect UI Components
 |  | Publish a Camera and Microphone
 |  | Subscribe to a Live or Recorded Stream
 |  | onStatus Catch-All Template (SSAS and Flash)
 |  | onSync Template (SSAS and Flash)
 |  | Connect and Create a Remote SharedObject (Flash)
 |  | Connect and Create a Local SharedObject (Flash)
 |  | Connect and Create a SharedObject (SSAS)
 |  | Connect a Database with Macromedia Flash Remoting MX Using SSAS
 |  | Connect a Database with Macromedia Flash Remoting MX Using Flash ActionScript
 |  | Invoking a Server Function from Macromedia Flash
 |  | Invoking a Macromedia Flash Function from SSAS
Index


Copyright

Copyright © 2003 by New Riders Publishing

Published by Macromedia Press, in association with New Riders Publishing, a division of Pearson Education.

First edition: December 2002

All rights reserved. No part of this book shall be reproduced, stored in a retrieval system, or transmitted by any means—electronic, mechanical, photocopying, recording, or otherwise—without written permission from the publisher, except for the inclusion of brief quotations in a review.

Library of Congress Catalog Card Number: 2002111249

Printed in the United States of America

06 05 04 03 02 7 6 5 4 3 2 1

Interpretation of the printing code: The rightmost double-digit number is the year of the book's printing; the rightmost single-digit number is the number of the book's printing. For example, the printing code 02-1 shows that the first printing of the book occurred in 2002.

Trademarks

Macromedia is a registered trademark of Macromedia, Inc. Other product names mentioned within this publication may be trademarks or registered trademarks of other companies. Throughout this book trademarked names are used. Rather than put a trademark symbol in every occurrence of a trademarked name, we state we are using the names only in an editorial fashion and to the benefit of the trademark owner with no intention of infringement of the trademark.

Warning and Disclaimer

Every effort has been made to make this book as complete and as accurate as possible, but no warranty of fitness is implied. The information is provided on an as-is basis. The authors and New Riders Publishing shall have neither liability nor responsibility to any person or entity with respect to any loss or damages arising from the information contained in this book or from the use of the programs that may accompany it.

Credits

Publisher

David Dwyer

Associate Publisher

Stephanie Wall

Editor in Chief

Chris Nelson

Production Manager

Gina Kanouse

Acquisitions Editors

Linda Anne Bump

Todd Zellers

Senior Product Marketing Manager

Tammy Detrich

Publicity Manager

Susan Nixon

Senior Development Editor

Lisa Thibault

Project Editor

Michael Thurston

Copy Editors

Kelli M. Brooks

Linda Laflamme

Indexers

Chris Morris

Lisa Stumpf

Proofreader

Sharon Provart

Composition

Wil Cruz

Manufacturing Coordinator

Dan Uhrig

Cover Production

Aren Howell

Cover Designer

Jean Rosevear

Dedication

To my family, my mom, dad, brother, and friends who are so incredibly important to me. Also to the team at Pangaea NewMedia who work tirelessly to steer the ship every day – you guys are awesome.


About the Author

Kevin Towes is co-founder and CTO of Pangaea NewMedia in Toronto, Canada. He is a certified Macromedia ColdFusion Developer and has led his team at Pangaea to achieve much success with Macromedia products for many years. Kevin is an industry leader in the fields of Macromedia Flash, ColdFusion, and database integration. He is also a passionate speaker on softer topics of interactivity, development workflow, and integrating culture and technology.

In 2002, he successfully organized the first-ever ColdFusion North Developers Conference. He also manages one of the largest ColdFusion developer user groups in the world. Kevin is a regular speaker at industry conferences, workshops, and schools throughout North America, including the annual Macromedia Developer Conference. He has co-authored feasibility studies for the Encyclopedia of Music in Canada and the Canadian Music Centre, attending to the digital migration of content to the Internet. He contributed to Inside Flash MX, a book published by New Riders, addressing the connection between Flash MX and application servers using Flash Remoting.

Kevin is a regular contributor to the Macromedia Flash Communication Server, Flash, and ColdFusion Developer Centers. His articles and tutorials provide techniques integrating Macromedia products and other relevant technologies. Kevin has a solid teaching foundation, including six years as part-time instructor at Ryerson University lecturing on the integration of digital media and culture. He currently holds advisory board appointments for the Canadian Film Centre and Macromedia.

He holds a BAA in Photographic Arts from Ryerson Polytechnic University. Kevin spends his free time as an avid rower, kayaker, and pilot.


About Pangaea NewMedia, Inc.

Pangaea NewMedia is an award-winning interactive media production company based in Toronto. Founded in 1995 by veteran film/video and music producer Tony Tobias and media technology architect Kevin Towes, Pangaea has been developing innovative and interactive web solutions for clients in some of the most dynamic industry sectors.

Pangaea specializes in content solutions for the Internet, TV, iTV, radio, and wireless. Pangaea's proprietary suite of interactive media solutions and tools allow those publishing content to the web and other media platforms to manage and control their own content. Pangaea sites and applications enhance the user experience while providing the maximum in functionality, simplicity of navigation, and best presentation of strategic content.

In 2000, Pangaea was one of the first companies to produce a full Flash web site with complete content management for Imported Artists (www.importedartists.com). The site has won various awards for its Flash design and underlying technology.

Pangaea was also one of the first companies to be awarded development funding from the Interactive Broadcast Development Group for the creation of an interactive television prototype. Pangaea demonstrated a fully functional iTV prototype, showcasing a new way of integrating television and the Internet for an interactive TV experience. Currently, Pangaea is participating in the MPEG-4 trials broadcasting from the CN Tower in Toronto, in collaboration with Canadian Digital Television, Inc. (CDTV) and Ryerson University.


About NI Solutions Group, Inc.

NI Solutions Group is providing the shared hosting environment on which the Macromedia Flash Communication Server applications used in this book are run. Established in 1992, NI Solutions Group has led the way for the revolutionary delivery of dynamic IT solutions and Internet services across North America. NI Solutions Group is a true managed service provider, delivering cutting-edge services and a flourishing range of comprehensive web solutions.

NI Solutions Group's commitment to their customers is paralleled and distinguished by the strength of the products they provide. Ultimately, it is the approach that NI Solutions Group takes to their value-added service offerings that demonstrate the strength of their managed hosting solutions.

You can learn more about NI Solutions Group, Inc. through their web site at www.nisgroup.com or by emailing info@nisgroup.com.


About the Technical Reviewers

These reviewers contributed their considerable hands-on expertise to the entire development process for Macromedia Flash Communication Server MX. As the book was being written, these dedicated professionals reviewed all the material for technical content, organization, and flow. Their feedback was critical to ensuring that Macromedia Flash Communication Server MX fits our reader's need for the highest-quality technical information.

Greg Burch is a Macromedia Flash engineer currently working at Macromedia, Inc. Greg has extensive Flash development experience with desktop and device applications and is an active developer on both. Located in Boston, Massachusetts, Greg is an active contributor to the Flash-Device community with contributions in several forms to the following books: author of Flash Design for Mobile Devices (Hungry Minds), technical editor of Flash Enabled: Flash Design and Development for Devices (New Riders Publishing), and source for Flash: The Future (No Starch Press, Inc.).

Greg is a founder and member of the Mobile Content Consortium (MCC). MCC is a group of leading mobile content developers, authors, engineers, and designers who aim to promote a higher standard of user experience, content and application design, and development for mobile platforms. Their slogan is "define or be defined." They're on the web at http://www.mobilecc.org.

Greg is a co-founder of the Flash Communication Framework project for the Macromedia Flash Communication Server. The project's goal is to provide a real-time, cross-platform framework for use on both the server side and client side. You can gain more info on the project at http://fcf.sourceforge.net/.

Greg maintains an active weblog at http://radio.weblogs.com/0107886/.

Eric E. Dolecki is a senior interactive and multimedia designer and developer based in Boston, Massachusetts.

His Macromedia Flash work appears on the Macromedia/ Centennial Media Advanced Flash 5 ActionScripting Training CD-ROM and past issues of Computer Arts UK magazine. He is co-author of Macromedia Flash Super Samurai (Macromedia Press), Flash MX Audio Magic (New Riders Publishing), and Flash MX Dynamic Applications (Macromedia Press).

In addition to published works, he has won numerous international Flash awards. Eric recently won the coveted Macromedia Site of the Day for his wireless FlashForward 2002 NYC Event Guide that runs on enabled Pocket PCs. Eric is a founding member of the Mobile Content Consortium. He is a regular contributor to several open source Flash sites and Flash community sites, and he maintains his own site, www.ericd.net, which showcases interactive design, Flash experiments and Flash source material. He manages his personal clients' work, and serves as a conduit between himself and those seeking to learn more about Flash and interactive design. He actively maintains and seeks to expand his list of clients.

Larry Drolet is one of the founders of Answer Studios, a design and application development house blending photography and Macromedia Flash application design. He is a developer and dreamer, one of those people when "well caffeinated" has about an idea a minute. While in graduate school, he was forced to write a paper on Internet law and it developed into a hobby, then a freelancing gig, a real dot-com job, a position with a dot-com start-up, and now his own firm. Sounds all too familiar! Currently, he is working on the fourth version of his site ToUnite.com, but he's looking forward to the day he can move on to his next career: either a lawyer or a professional triathlete. Larry can be seen every month at the San Diego Server-Side User Group—coding guaranteed to put you to sleep.

John Grden is a lead Macromedia Flash programmer for zing.com along with Ian Suttle. His passion is Flash and anything having to do with Flash. He's most drawn to creating the most engaging games possible using Flash and pushing its limits. Now with the release of Macromedia Flash Communication Server MX, John's creative world has opened up exponentially with regards to real-time multiplayer gaming experiences using Flash. See what he's been up to at www.AcmeWebWorks.com.


Acknowledgments

Writing this book was much different than most projects I am involved with. Most times, developers are not afforded the luxury of learning new technology to the fullest extent of what it can do. Like most of you in developer or CTO roles, I look at a technology, quickly assess how it can affect my business and solutions, and do some analysis to develop a few quick applications to test its integration.

This process usually provides a sufficient top-level view of what the technology can offer. The Macromedia Flash Communication Server is such a radically new concept that I admit to being intimidated at first. You are probably feeling the same way. When you write a book like this, you must look at every nook and cranny of the technology. Because this is so new, there are no methodologies or best practices to follow. There are no pre-determined specific guides or recommended approaches. Even the manual contains a section called "Tips and Tricks" versus recommended practices. The manuals are adequate, but do not provide the bigger picture. Because there are so many elements to this server, I found that having multiple sources of information complexes things unnecessarily.

I hope this book gives you the leverage you need as a jumping board for this incredible technology. I must start the acknowledgments with the Macromedia engineers and beta testers that worked on this project. The technology is a solid release and is ready for Prime Time. The launch of all the MX products must have made it tough to ensure tight integration and a solid top-level understanding and passion for the technologies and the platform. CTO Jeremy Allaire has served Macromedia very well in his role for the Communication Server. He is extremely passionate about Internet technology, and if you get a chance to have a conversation with him, I am sure you will draw the same conclusion. Jonathan Gay, Macromedia Technology Vice President, also deserves recognition for his contribution in developing a brand new technology pushing the limits for Internet communication.

Peter Ryce and Heather Hollaender from Macromedia's product management team were an invaluable resource to me. They patiently answered the many questions I had over the course of writing this book, and I thank them for their passion and dedication to the product.

The Flash Communication Support Forums and Fig Leaf's Chatty Fig "FlashComm" Listserv provided me the facility to interact with developers who were going through the learning steps. These forums and lists were also invaluable to address some of the common problems that plagued people during the learning process.

All examples in this book can be seen in working order at http://flashCom.PangaeaNewMedia.ca/. Thanks to our friends at NI Solutions Group, Inc. (www.nisgroup.com) for providing the Shared Hosting environment.

If you have ever written a book, article, or even a letter, you know that you cannot do it alone. Thank you to all the technical editors (credited earlier). Your constructive comments, insights, and critique made this book the best it could possibly be. From New Riders, thank you to Lisa Thibault and Linda Bump for believing in me and making this project come together tightly and professionally. A personal "thank you" to Greg Burch for contributing one of the tutorial chapters under a very tight timeline.

Finally, I would like to acknowledge the team at Pangaea NewMedia who had to put up with me over the course of writing this book. Our production manager, Rick Mason took every chapter home when it was complete, and stepped through each exercise, returning excellent critique and suggestions to protect me from embarrassing myself. To Rick, Steph, Irina, Jean, Malia, Heather, Michelle, Hugh, and my business partner, Tony Tobias, thank you for your support and encouragement.


Tell Us What You Think

As the reader of this book, you are the most important critic and commentator. We value your opinion and want to know what we're doing right, what we could do better, what areas you'd like to see us publish in, and any other words of wisdom you're willing to pass our way.

As the Senior Acquisitions Editor on this book, I welcome your comments. You can fax, email, or write me directly to let me know what you did or didn't like about this book—as well as what we can do to make our books stronger. When you write, please be sure to include this book's title, ISBN, and author, as well as your name and phone or fax number. I will carefully review your comments and share them with the author and editors who worked on the book.

Please note that I cannot help you with technical problems related to the topic of this book, and that due to the high volume of email I receive, I might not be able to reply to every message.

Fax: | 317-581-4663
Email: | linda.bump@newriders.com
Mail: | Linda Bump Senior Acquisitions Editor New Riders Publishing 201 West 103rd Street Indianapolis, IN 46290 USA


Foreword

On March 13, 2002, Macromedia unleashed one of the most important software releases in the history of the Internet, Macromedia Flash Player 6, which would quickly become the fastest adopted piece of software in the history of computing. With nearly three million downloads and installations every day, this rich client rapidly became a core component of nearly every Internet-connected computer.

Unknown to the end users downloading the new player at the time, and even to the existing one million-plus Macromedia Flash designers and developers, the player contained a series of new player capabilities centered on enabling communications and collaboration on the Internet. The new player combined the rich media and user interface prowess of Macromedia Flash with the ability to communicate and collaborate in real-time—sharing audio, video, data, and user interfaces. As one Macromedia employee commented at the time, "It's as if we were distributing hundreds of millions of next-generation communications devices, and then later suddenly turning them on."

In July 2002, Macromedia launched Macromedia Flash Communication Server MX, delivering the final piece of the puzzle that would enable the creation of revolutionary communications applications. Quickly, designers and developers around the world jumped in to use Macromedia Flash Communication Server MX, exploring its power and experimenting with the combination of media, applications, and communications that it makes possible.

This book is the first in what I'm sure will become a library of knowledge and content about Macromedia Flash Communication Server MX. It is an important book, and one that articulates the capabilities and power of this new technology in an approachable, hands-on manner.

I've been involved with the Internet for more than 12 years, and have experienced its growths and transformations. There are few Internet technologies that truly have changed the nature of computing media and applications. E-mail and the World Wide Web are certainly examples. My own introduction to Macromedia Flash Communication Server MX last year left me with a deep feeling of awe; one that convinced me that this technology would almost certainly help shape the Internet in as broad a way as these past "killer applications" have.

Dig in, read up, and build some cool stuff. Your work will certainly help change the face of the Internet.

—Jeremy Allaire
CTO, Macromedia


Preface

The phone rang just after I arrived at my office following a very uninteresting commute from the suburbs of Toronto. A familiar and friendly voice was on the other end. It was Linda. Linda is an acquisitions editor at New Riders Publishing. We had worked on a project together earlier that year.

After some light small talk, she cut to the chase, as she is prone to do. "Kevin," she said, "Would you be interested in writing a book?"

"A book," I said, all the while wondering what she thought I had to say to the world. "What about?" I have to admit I was intrigued.

"Tin Can," Linda said excitedly. Now, Linda always sounds excited over the phone, but this time it was different. It was the kind of excitement that you couldn't say "no" to.

I thought about it that morning over an especially strong cup of coffee. Tin Can was the code name of the long anticipated release of Macromedia Flash Communication Server MX. I wasn't too worried about the technical challenge; I could handle that. I was more concerned about the book's approach and the challenges of introducing concepts that were so new.

Ok, I decided if I was going to write a book, I had to have some "story-telling" element to it.

And here is the result. I started this section with a traditional form of communication: an expressive story told using the written word. Now, my story-telling skills may need work, but the opening anecdote illustrates what this book is all about—communication. This book is about building technology to help us communicate with each other in a more human way.

The problem with many software programs is that the talented engineers have focused on issues of technology and not human interface. Everyday we are forced to deal with amazing technology through poor user interfaces. The Flash Communication Server is a technology framework that abstracts connectivity and platform concerns to a level where developers don't have to be concerned about them any more.

This is not to say that the Flash Communication Server will solve human interface problems. It won't. It does, however, take care of some of the technical plumbing so that you can focus on how people will communicate. The Macromedia Flash MX authoring environment and Macromedia Dreamweaver MX are the integrated development environments (IDE) for creating Flash Communication Server Applications on the Mac and Windows platforms. These technologies are accessible to literally millions of developers, designers, animators, and engineers in every country and in every language. Plus, new techniques and an awesome collection of Flash UI components make it simple and quick to start working with the Communication Server.


Exactly What Is Macromedia Flash Communication Server MX?

Flash Communication Server MX is an enterprise-grade server technology that facilitates connections between the Flash 6 players, .NET, and J2EE application servers and other Flash Communication Servers. The 1.0 release of the server is supported on the Windows platform only.

An application that uses the resources of a communication server is called a Flash Communication Application. Flash Communication Applications can be distributed over a local network or across the Internet using a traditional web server on any server platform (Mac, Unix, Windows). Applications are executed within Flash Player 6, independently, or embedded with a web browser that supports the Flash Player 6 plug-in.

How Does the Flash Communication Server Work?

The Flash Communication Server is a hub. Flash players connect to the hub using Macromedia's bidirectional communication protocol called Real-Time Messaging Protocol (RTMP). As the hub, the Flash Communication Server can easily connect to other communication servers (hubs) to increase user and bandwidth capacity. The Flash Communication Server can also connect to J2EE, web services, and ASP.NET application servers to extend applications with database connectivity and other server resources, such as an email or LDAP server.

The connection between client and server or server and server supports multiple one-way streams published or received by a client or the server. The Flash Communication Server has a powerful programming model called SharedObjects. SharedObjects synchronize complex data and send one-way messages between clients connected to the server.

Regular ActionScript objects are transported across network connections using the Action Message Format (AMF). This format is used over a non-persistent HTTP or secure HTTPS connection when exchanging data with application servers. The format is also used over the persistent RTMP when exchanging data between client and server. AMF is a binary format that is handled transparently by the server and Flash Player 6.


Why Is Flash Communication Server Needed?

The Flash Communication Server solves two very specific issues in the world of Internet-based communication:

  • A development environment

  • Technology adoption across platform and device

It solves these problems by connecting Flash players together and leveraging the sophistication of the Flash MX authoring environment.

The Flash Communication Server takes care of the communication "plumbing" and allows the developer to focus on quickly building communication applications that are easily integrated into a business or creative environment. The communication server provides the building blocks for Flash applications to communicate with each other using a standard object-oriented scripting language: ActionScript, which is based on JavaScript.

Flash Communication Applications are delivered using Flash Player 6, the most universally adopted software that has ever been produced. Flash Player 6 is available across all platforms and is supported by a growing number of mobile devices, such as the pocket PC. This acceptance and distribution breaks through a major barrier faced by any new application hitting the market for the first time. Developing applications that use Flash Player 6 lets developers focus instead on what is key—the communication experience.

The SWF file format, which Flash Player 6 uses, is an open standard adopted by television and film production tools, 3D animation software, and now Internet-based communication technology. Flash Player 6 is the most universally accepted new release product ever with a 68% market saturation just six months after its release in May of 2002.

Macromedia has changed everything with the Communication Server. The company calls it a revolution, which is a pretty accurate description. The traditional client-server relationship of Internet applications was simple: Someone asked for something, and you gave it to them, as in HTTP and the client-request method. JavaScript allowed you to place data and logic on the client, autonomous from its origin. Databases and application servers made life easier by separating content from display logic. This brought on the content-management revolution.

In the early 1990s, the basics of Internet communication were just starting. There was messaging over the Internet, both live and offline, but they were not practical parts of web page concept. The arrival of streaming application servers and XML in the late 1990s changed the perception. The Flash Communication Server has just added another layer of complexity to everything, bringing about a fundamental change in thinking about Internet applications.

A New Paradigm for Communication

As humans, we want to communicate, but the machines that "enable" online communication are very "offline." So much technology has allowed us to talk not with each other, but with computers instead. Consider how you interact with your telephone's voicemail system: You use the keypad to enter a series of numbers, even though the technology supports voice input! The same is true of saving a name in your cell phone address book; you press 1 for a, b, and c, 2 for d, e, and f, and so on. So, why are we trying to be connected all the time if everything we use is offline?

In a Macromedia newsletter, the company's chief technology officer, Jeremy Allaire, describes the Flash player as a Trojan Horse. He describes delivering hundreds of millions of Flash 6 players to the market as "distributing several hundred-million next generation communications devices—and just now turning it on."

To understand what he means, consider the recent trends in gaming and instant messaging. Battle.net enables game manufacturers to connect their games together, so humans can compete with humans regardless of location. Game consoles, such as Xbox and Playstation, will soon introduce network gaming and player-to-player voice communication through the game. This new technology will allow gamers to play a hockey match with a player somewhere else on the planet. Another indication of the communications shift is the popularity of instant messaging from AOL, MSN, and Yahoo!.

Such hardware devices as Cybiko (http://www.cybiko.com) target a consumer market with sophisticated communication technology wrapped in an interface that is easy to understand.

It is more than clear that we are starting to consider technology as a formidable means of communication. The Flash Communication Server is exciting for developers not only because it has already been adopted and distributed for you, but also because your time has been freed up to focus on delivering the messages of others in a more "human" way. It is now up to you to enable us to communicate in new ways.

So, get comfortable and get ready to be inspired!


Who Is This Book for?

Flash Communication Server MX is for developers familiar with building Flash applications. Developers who are versed in object-oriented programming using JavaScript or Flash ActionScript will gain a unique advantage and learn to leverage the real power of the server. This should not discourage developers new to ActionScript or even Flash MX. The first 10 chapters will walk you slowly through foundation concepts and basic exercises designed to step you through each element and process.

This book is also for server administrators and Internet service providers considering offering the Communication Server as a shared hosting solution.

The book provides a strong technical and contextual background to get you building and distributing applications quickly, from installing the server to building a work environment to scripting complex applications. There's context, code, design, and even some humor thrown in.


What Does the Book Cover?

Flash Communication Server MX walks through 10 quick steps to get you started. Beginning with the install process, you will move quickly to a basic implementation of the Flash UI components and simple ActionScript. Some advanced exercises will give you the footing you need to be successful with Flash Communication Server MX. The book will follow up the 10 steps with a detailed overview of the communication objects available on the server and within the Flash MX authoring environment. Detailed reviews of server administration, connecting databases, and development techniques also will be presented.

Three real-world workshops will introduce you to methods of developing communication applications, games, and training and education applications. You will walk away stunned and amazed at the new possibilities of Macromedia Flash MX, when combined with the Macromedia Flash Communication Server.

You will discover that developing rich and connected applications with Flash MX and the Flash Communication Server is very quick and painless. If you are not a Flash programming expert, don't be scared; you will build communication applications with no ActionScript over the first five steps! Get ready for a shock: You don't need any code to be productive with the Communication Server. Once through the introductory chapters, you will gain a deeper insight into the Communication Server's operation using server-side ActionScript.


What Are the Software Requirements?

You must have a few things in place before you get started.

Make sure you also have Flash MX installed before putting the Communication Server on the same workstation. If you use Flash MX on the Mac, you can develop Communication Server Applications. You will not, however, be able to test your application without a Windows-based server. Version 1.0 of the Flash Communication Server is available for Windows platforms only. The manual process to install the Communication Components on your Mac will be discussed later in this chapter. Here are the requirements to get started:

  • Flash Communication Server (any edition)

  • Macromedia Flash MX (trial or full version on Windows or Mac OS)

  • Macromedia ColdFusion (any version; you'll use this in the Flash Remoting MX examples)

  • Sorenson Squeeze (trial or purchased version)

  • The most recent version of the Flash player

  • Windows XP Professional, Windows XP Home, Windows 2000 Professional, Windows 2000 Server, Windows 2000 Advanced Server, or Windows NT 4.0 Workstation SP6 or later

  • Windows Web Services IIS (recommended, but not required)

  • A web browser with Flash Player 6 installed (Microsoft Internet Explorer is recommended)

  • Multimedia hardware: web camera (or live video source), microphone, and headphones or speakers for each "connected" computer

Having a web server installed is also a good idea, but is not required. If you do want to run the Communication Server with a web server, set up the server before you install the Communication Server.

If you are considering using the Flash Communication Server for a one-time event or application and don't want to worry about managing the server, bandwidth, or licensing, you can use a Shared Hosting company to supply you with Flash Communication Server access. Since Macromedia released the Flash Communication Server, many Internet Hosting companies have started to offer Flash Communication Server Hosting as part of their shared service. One company, NI Solutions Group, Inc. (http://www.nisgroup.com), offers Flash Communication Server hosting at very reasonable rates. They are also hosting all the example applications that are presented in this book (http://flashcom.PangaeaNewMedia.ca).


Trial Software and Downloads

If you don't have the listed software, you can download free 30-day trials from these links:

  • Macromedia Flash Communication Server (Professional Edition): www.Macromedia.com/go/flashcom/

  • Macromedia Flash MX (Mac or Windows): www.macromedia.com/software/flash/

  • Macromedia Flash Debug player (Mac or Windows): www.macromedia.com/support/flash/downloads.html www.macromedia.com/go/getflashplayer/

  • Macromedia ColdFusion MX, Macromedia JRUN 4 (Windows or Unix): www.Macromedia.com/go/coldfusionmx/ www.Macromedia.com/go/jrun/

    (Note, these servers are used for the exercises that involve Flash Remoting MX. You can also use any J2EE application server that is enabled for Flash Remoting MX or the ASP.NET Framework. For details, visit www.Macromedia.com/go/flashremoting/.)

  • Sorenson Squeeze (Mac or Windows): www.Sorenson.com/

  • Web Server (Windows, Mac, J2EE)

This book focuses on Flash Communication Server MX; please consult the individual software manuals for Flash MX and other programs for installation requirements and procedures. Your 10-step journey into the world of Flash Communication applications will start by installing the Flash Communication Server in Chapter 1, "STEP 1: Installation and Setup."


What Is on the Web Site?

All exercise source code, errata, and updates will be posted to the book's web site:

http://flashcom.PangaeaNewMedia.ca/

Additional tutorials and exercises may be posted, as well. Live Flash Communication web casts will occur at regular intervals to help you with any problems you might have with the server implementation. Keep an eye on the site as you jump into developing applications with the Flash Communication Server MX.


Part I: 10 Quick Steps for Getting Started

1 STEP 1: Installation and Setup

2 STEP 2: Your Development Environment

3 STEP 3: Get Connected

4 STEP 4: Simple Chat and Video Conferencing

5 STEP 5: Monitoring and Managing the Server

6 STEP 6: ActionScript with NetConnection()

7 STEP 7: Streaming Video with NetStream()

8 STEP 8: Collaboration with SharedObject()

9 STEP 9: Controller and Subscriber Applications

10 STEP 10: Lobby Applications


Chapter 1. STEP 1: Installation and Setup

This chapter will step you through the process of installing Macromedia Flash Communication Server MX. To ensure your install goes smoothly, an overview of the installation options will help you make preparations before you install. After the install is complete, the management tools and the Flash UI components will be quickly introduced to you. This chapter will also review how to install the authoring components on other workstations not on the server, including the Mac operating system.


Installation and Setup

There are two editions of the Flash Communication Server: the Personal edition ($499 US) and the Professional edition ($4,500 US). These two packages are almost identical in their feature set. The principle differences are capacity limitations with concurrent user connections, multiple hosts, and bandwidth. The price is the other considerable difference.

If you are just getting started with the technology, or just want to test it out, Macromedia offers a 30-day free trial of the Professional version. The trial gives you the full functionality of the Professional edition. This entire book was written using the Professional Trial edition. Macromedia has also produced a series of unique Communication UI components for Macromedia Flash MX. The components provide quick solutions for building chat rooms and connecting cameras and microphones to Communication Server. The components are available free of charge from the Macromedia web site (http://www.Macromedia.com/go/flashcom/). This book will use these UI Components extensively, so be sure you download the most recent version. Unlike other Macromedia server trials, Flash Communication Server Trial will be completely inoperable after the 30-day evaluation has expired.

Let's start our journey to the great unknown by first reviewing your options.


The Personal Edition

The Personal edition of the Communication Server is great for a development environment or for small-scale communication solutions. Applications for internal use or to keep in touch with friends and family are also good candidates for this edition. For almost a tenth of the Professional edition price, you have 10 simultaneous connections and 1 megabit-per-second transfer speed. What does that mean? Up to 10 people can be connected at any one time. The bandwidth limitation for this edition will be reached if your application is streaming a 100k/sec video clip to 10 remote clients. In this example, the server is sending each user a 100k stream. This will reach the upper bandwidth limit of this edition if there are 10 users connected. Bandwidth will be discussed in Chapter 7, "STEP 7: Streaming Video with NetStream()."

If you intend to use the Communication Server for a larger-scale solution, such as a public web cast of a rock concert or have your corporate AGM web cast to shareholders and employees or even offer it as a shared hosting service, you have two options: You can purchase additional Personal editions and chain them together to increase bandwidth and user capacity or you can purchase the Professional edition. The process of chaining servers together will be presented in Chapter 11, "Server-Side ActionScript (SSAS)."


The Professional Edition

The Professional edition is almost exactly the same as the Personal edition. This edition includes additional user connections and an increased bandwidth capacity. Advanced security features, the ability to scale the server with multiple hosts, and an included one-year update subscription are also notable features of this edition. This edition should be considered if you have a high-volume service or if you want to host multiple secure applications. A good example would be a company that offers public Flash Communication Server hosting. The Professional edition can group applications using a method of virtual hosting.

This edition starts with 500 concurrent connections (versus the 10 connections offered in the Personal version) with a maximum bandwidth of 100 megabits per second. If you require additional connections and bandwidth, Macromedia offers upgrades through Capacity Packs. Although there are no formal statistics published by Macromedia, there have been unofficial declarations that this version supports 1000+ simultaneous users of multiple connection speeds. Capacity Packs can be purchased to increase the number of users and the bandwidth capabilities. Each Capacity Pack increases concurrent users by 500 and bandwidth support an additional 10 megabits per pack. Pricing for the Professional edition is comparable to enterprise-level applications.

The Communication Server can be scaled to exist in a load-balancing and server-failover environment. The foundation of the server has been developed with this in mind, making it a true enterprise application that can be used to allow communication with as many users as you need.

If you are considering developing Flash Communication Server applications but don't quite need the performance and scalability of the Professional edition, shared-hosting companies are starting to appear in the market. Pricing models are built around concurrent connections and bandwidth required. This option is a great way to get started with the technology with a small initial investment.

NI Solutions Group, Inc. (http://www.nisgroup.com) is one of a number of Internet hosting companies that offer Flash Communicaiton Server as part of a Shared Hosting Solution.


Before You Install

The Flash Communication Server is one of the easiest server installations you will experience. There are, however, a few considerations before running the installer:

  • First, be prepared to set up a server administrator password. This login and password will be used to monitor and control the Communication Server from the two management utilities that will be installed.

  • Next, determine if this install will be a development or production (live) install. In other words, will you be using the same machine that you install the Communication Server on to develop applications in the Macromedia Flash MX authoring environment? If so, install Flash MX before you install the server. The Communication Server will install important extensions to the Flash MX authoring environment. To make it easier for you, it helps to have Flash MX installed first.

Tip

If you are planning to install the Communication Server on your local workstation, ensure that the Flash MX authoring environment is installed first and a web server (preferably Windows IIS) is installed and running before you install the Flash Communication Server. Having these two elements installed will let the installer set up the authoring components. This will save a lot of time installing the authoring components manually.

The installer will prompt you to declare how to set up the server. The two options are Development and Production. Let's look at the difference.

Development Option

The Development option installs the "application" files and the sample applications into the local web server root folder (more on this in a moment). This allows you to conveniently store the Flash (FLA, SWF) files in the same place as the server application files while you are in development. Flash Communication Applications have two principle parts to them. First, there are client (or outside-facing) files such as HTML and SWF (Flash movie) files. Second, each communication application uses special server-side components that, for security reasons, should not be accessible through a public web interface when you deploy. These resources are accessible only by Flash Player 6 through a special protocol (RTMP) and ports. Securing Flash Communication Applications will be discussed in Chapter 15, "Communication Application Architecture Strategies."

Production Option

The Production option installs the application files outside of any web server root that may exist on the computer. The Flash Communication Server does not use a web server to communicate with the Flash Player 6 clients. As noted in the introduction, it uses the RTMP protocol to transmit ActionScript objects and message broadcasts using Action Message Format (AMF). This is not the same as the HTTP (web) protocol that a web server uses.

Objects that are transmitted by the communication server include server-side ActionScript (SSAS), remote SharedObject (FSO) files, and Flash Video (FLV) files (also known as recorded stream files). It is good security practice to not include these files in any folder publicly accessible by a web server to eliminate any temptation for malicious users to hack your application and expose sensitive or secure information. This does not mean that, if you choose this option, you cannot use the server for development. It only means that your HTML and SWF files should be placed in separate locations and you should access them remotely through a web browser.


Ports

As mentioned in the Preface, the Flash Communication Server uses a proprietary protocol, RTMP. This protocol is used to transfer data and messages between Flash Player 6 and the Communication Server. This protocol does not interact with the web server protocol, HTTP. Most web servers run (by default) on ports 80, 81, or 8080. Microsoft web server ports are set up in the IIS Manager, where the IP Address is set. Knowing what port your web server is communicating on will ensure that you do not set the Communication Server to use the same ports.

The Communication Server uses two ports in its operation:

  • Admin Port (default: 1111). Used by the management consoles to monitor and control the server remotely. This is an important port to keep private, especially on production servers. Access to the administration controls allows a user to halt or restart the server or interrupt applications. You don't want unauthorized users to have access to these areas. There will be more discussion on blocking access to the server administration in Chapter 13, "Accessing External Data."

  • Server port (default: 1935). This is used by the server to maintain persistent connections with Flash Player 6 and other Flash Communication Servers. If you change this port number, your Flash movie must include the port number in the connection string. Firewalls may pose a problem if these ports are blocked. Your network administrator can allow communication through these ports or assign you ports you can use. If you have a personal firewall, make sure you open the ports you plan to use. Only the application port (1935) needs to be accessed. Port 1111 can be limited to a local connection or connected within your virtual private network (VPN). Disabling the 1935 port will restrict connections outside your network from accessing the Flash Communication Server. If you are using the server as a development server, on your localhost (your workstation), you do not need to worry about firewalls.

Note

Both of these ports have been assigned to the Flash Communication Server by the Internet Assigned Numbers Authority (IANA). For more information on this group, visit http://www.iana.org.


Installation

In this book, I assume that you install your server on a machine with a Windows IIS Web Server with the default Development options. References will be made to these locations:

  • Target Directory: C:\Program Files\Macromedia\Flash Communication Server MX\

  • Support Files Directory: C:\Inetpub\wwwroot\flashcom\

  • Applications Directory: C:\Inetpub\wwwroot\flashcom\applications\

  • Flash MX Directory: C:\Program Files\Macromedia\Flash MX\

  • Server Port(s): 1935; Admin Port: 1111

If you are using a shared Communication Server hosting supplier, the Internet service provider (ISP) will supply most of these details.


Macromedia Flash MX Components

The installation process installs three new features in your Macromedia Flash MX authoring environment. If you don't have Flash MX installed or you are running Flash MX on Mac OS, you will have to manually set up these new components if you are using the Trial edition. Macromedia does not provide a downloadable installer to install the components in Mac OS. Each section that follows includes steps to install these components manually. The Flash Communication distribution CD contains a Windows and Mac OS installer to install the authoring components in Flash MX.

Macromedia Flash Communication UI Components

The Macromedia Flash Communication UI components are a collection of special prebuilt Flash movies you can use to quickly build communication applications (see Figure 1.1). When they are installed, the UI components can be found by accessing Window, Components (or pressing Ctrl+F7) in the Flash MX authoring environment. Macromedia may update these components and add additional components. After installation, visit the www.Macromedia.com/go/flashcom/ web site to download the updates. They are great for building applications and serve as a foundation for learning the technology. You will get very familiar with them in the steps to follow.

Figure 1.1. The Flash Communication UI components.

Communication UI Components: Manual Install Option

If Flash MX is not installed on the computer, or you want to install the UI components to other computers (including Mac OS) running Flash MX, follow these steps to install them:

  1. Close the Flash MX authoring environment.

  2. Locate the file Communication Components.fla on your CD or download it from http://www.Macromedia.com/go/flashcomm/.

  3. Mac and PC users place the FLA file inside the folder [%Flash MX Install Path%]\First Run\Components\.

  4. Open Flash MX. It now appears in the Windows menu.

Communication App Inspector

The Communication App Inspector lets you monitor your application on the server (see Figure 1.2). It can connect to any Communication Server provided you have the proper security access. You will find this tool by clicking Window, Communication Application Inspector in the Flash MX authoring environment. This great tool allows you to monitor live logs (server Trace output), streams, SharedObjects, and general application statistics. It is an invaluable resource for developing your application and monitoring who is connected. We will get more into this feature in Chapter 5, "STEP 5: Monitoring and Managing the Server."

Figure 1.2. The Communication App Inspector.

The Communication App Inspector can be installed on any computer with Flash MX installed. Simply run the installer, select the Custom Install option, and uncheck the Server Install. The trial edition does not support a Mac OS installer. Refer to the book's web site for Mac OS manual install instructions. If you have a licensed copy of Communication Server, use the distribution CD to install the authoring components on Mac OS.

NetConnection Debugger

The NetConnection Debugger is another great tool to help monitor and debug your communication applications (see Figure 1.3). This unique debugger allows you to watch communication between the Flash player and the server. You will find the new Debugger by clicking Window, NetConnection Debugger in the Flash MX authoring environment. The NetConnection Debugger is not only used with Communication Server, but also Flash Remoting MX applications where the player is connected to J2EE or .NET application servers that are supported by Flash Remoting MX, such as Macromedia ColdFusion, JRUN 4, or ASP.NET. We'll get more into Flash Remoting MX in Chapter 13, "Accessing External Data."

Figure 1.3. The Flash MX NetConnection Debugger displaying some sample debug data.

The NetConnection Debugger can be installed on any computer with Flash MX installed. Simply run the installer, select the Custom Install option, and uncheck the Server Install. The trial edition does not support a Mac OS installer. Refer to the book's web site for Mac OS manual install instructions. If you have a licensed copy of Communication Server, use the distribution CD to install the authoring components on Mac OS.


After the Server Installation

Getting excited yet? You should be aware of just a few more details before jumping in.

First, let's make sure your installation went correctly by accessing the Flash Communication Server Administration Console (see Figure 1.4). If you installed the server using development mode with a web server, you can browse directly to the console by using this URL: http://localhost/flashcomm/admin/, where localhost is the name or IP address of your server.

Figure 1.4. The Flash Communication Server Administration Console.

You can also run the Administration Console by locating and double-clicking the admin.html file in the flashcomm/admin folder. This folder was specified in the install as the "support files directory." The default was c:\inetpub\wwwroot\flashcomm\.

The administrator can also be accessed through the Windows Start, Programs, Flash Communication Server MX menu.

When you arrive at the console, you will have to log in. If you installed this application on your local computer, leave the host field as localhost; otherwise, enter the server name or IP address in the host field. By default, the server will assume you are using port 1111; however, if you changed it during the install, declare the alternate port number following the server name, as in localhost:portNumber.

Enter the default server administration login and password you assigned during the install and press the Connect button. If your installation was successful, the yellow connection light at the top right should turn green, and you should enter the Administration Console. Immediately, click the Ping button inside the console. This sends a request to the server to respond, which will be measured and reported. In Figure 1.5, the round-trip time was 40 milliseconds. A slow connection time may result in poor performance.

Figure 1.5. The Communication Server Administration Console reporting a 20ms ping result.

Take some time to quickly familiarize yourself with the Administration Console. We cover it with more detail in Chapter 5. Familiarize yourself with the Maintenance tab—in particular, the controls that restart the server. If it becomes unresponsive, you may need to give it a restart. Be sure to run some of the example applications (located in the Getting Started menu) to further test your multimedia equipment after the server installation. If you feel curious, open some of the example FLA files in Flash MX and take a look at how some of the UI components are used.

The full documentation of the server is included in this window as well as useful links back to www.Macromedia.com. Also, be sure to check out the nifty credits page to pay homage to the developers who made this server a reality.

The next chapter walks you through setting up your production environment and understanding the server-side application structure for communication applications.


Summary

In the next chapter, you will set up your development environment. You will learn how the server files are organized and will be introduced to your Authoring environment, Macromedia Flash MX. A key stage in developing Flash Communication applications is the testing process. Chapter 2, "STEP 2: Your Development Environment," will review some ways to test your applications.


Chapter 2. STEP 2: Your Development Environment

This chapter will explore the files and folders that were installed on your server. Knowledge of the Macromedia Flash Communication Server MX development environment is important for a successful development experience. If you are not familiar with Macromedia Flash MX, this chapter will give you a quick introduction. Testing will be the focus—in particular, setting up your testing environment. Because you are building communication solutions, you may at times realize you are talking to yourself. It's okay; we've all done it. We'll start with the server, and then look at Flash MX.


The Server Files

The Communication Server has a unique file structure that may be overwhelming at first sight. As you will learn, it is a solid and secure structure that enables the server to scale to your needs easily and securely.

Two main folder structures will be examined:

  • The flashcom applications folder

  • The server configuration folder

For this discussion, assume that [wwwroot] is the root of a Windows IIS web server running on Windows 2000 Server or Windows 2000 Professional.

Flash Communication Server MX is structured into adaptors, virtual hosts, and applications. Adaptors contain virtual hosts, which contain your Communication applications.

Greater detail on this structure will be presented in Chapter 14, "Server Administration." Being aware of this structure before you dive in will help you grasp what's going on. For now, assume that your server has one adaptor and one virtual host (the default virtual host). Multiple applications will be created inside the default virtual host.

The Flashcom Applications Folder

This folder contains the server-side components of your Communication applications (see Figure 2.1). If you opted for the developer install, this structure is located in your web server's default root folder (default: c:\inetpub\wwwroot\).

Figure 2.1. The default applications folder as seen inside Macromedia Dreamweaver MX. Each Communication application is declared as a folder under the applications folder.

The flashcom\applications folder stores the server-side resources used by your Communication application. Applications are defined on the server by the existence of this folder. The folder creates a server space for the resources your application will use. If this folder does not exist, your Communication application will not work.

Inside this folder a series of server-side files can exist:

  • ASC files. Contains server-side ActionScript (SSAS). Server-side ActionScript is exactly like Flash ActionScript and is also based on the ECMAScript-262 specification derived from JavaScript. All server-side ActionScript stems from one of two files: main.asc or a file with the same name as the application (myApplication.asc). Use SSAS to script in protected security or business logic for your application. SSAS has ultimate control over all resources used by an application and can reference external resources such as Application Servers using Flash Remoting MX for database access. You will be introduced to ASC files in Chapter 6, "STEP 6: ActionScript with NetConnection()," with full details in Chapter 11, "Server-Side ActionScript (SSAS)."

  • FLV and IDX files. Pre-recorded streams that include video, audio, or still images stored in the FLV format. FLV files are created from standard digital video formats (such as Apple QuickTime or Microsoft AVI) using Sorenson Squeeze. The Communication Server also creates them dynamically if your application is set to record video or images. FLV files are the source files used to stream pre-recorded media to the Flash clients. The index file (IDX) is used by the Communication Server to log and manage the FLV file. These files will be explored in detail in Chapter 7, "STEP 7: Streaming Video with NetStream()."

  • FSO files. Persistent SharedObjects used by Communication applications to exchange data across all clients. SharedObjects will be introduced in Chapter 8, "STEP 8: Collaboration with SharedObject()," with more details in Chapters 11 and 12, "Client-Side (Flash) ActionScript."

Note: These are not the only files required by the Communication Server. You will also need HTML, Flash MX (FLA), Flash movie (SWF), and possibly Flash MX Debugging (SWD) files. During the development process, it is recommended that these additional files be stored in the server applications folder. When you move the application to a production server, for security reasons (explained in Chapter 14, "Server Administration"), your front-end files (HTML and SWF) should not exist in this folder, but separately within your web server.

At this point, you may be getting confused over the files. Table 2.1 lists every file that can be used by Flash Communication applications, describes what application the file is accessed by, and how it is created.

Table 2.1. Matrix of files used by Flash Communication applications.

File

Used By

Type

Authoring

Description

.AS

Flash MX

Source

Dreamweaver MX

External Flash ActionScript source file

.ASC

Flash Communication Server

Source

Dreamweaver MX

Server-side ActionScript source file used by the Communication Server

.ASR

ColdFusion MX

Source

Dreamweaver MX

Server-side ActionScript source file used for Flash Remoting MX by ColdFusion MX

.FLA

Flash MX

Source

Flash MX

Flash MX authoring source file

.FLV

Flash Communication Server

Compiled

Flash MX, Communication Server MX, or Sorenson Squeeze

Recorded Flash video

.FSO

Flash Communication Server

Compiled

Flash Communication Server

Persistent SharedObject (on the server)

.HTML

WebServer

Source

Dreamweaver MX

HTML container

.SWF

WebServer

Compiled

Flash MX

Compiled Flash Player 6 movie

The flashcom\admin folder is the home for the Flash Communication Server control panel. There is nothing special about the HTML version of the administrator other than it is a convenient way to access the help and provides easy access to the two primary management tools.

The management tools that shipped with the Flash Communication Server include the Administration Console (admin.swf) and the App Inspector (app_inspector.swf). Being loyal to its technology, Macromedia has built the applications with Flash MX to help you manage and monitor the Communication Server. Being Flash-based, these tools will run anywhere Flash Player 6 can be installed. They do not need to be accessed from the server, but can be run locally outside the HTML console or included in a larger administration application that you may have.

There will be more detail on the these two applications in Chapter 5, "STEP 5: Monitoring and Managing the Server."

Tip

You can have direct access to these two applications from within Flash MX. Place the admin.swf file into the folder: [%FlashMX Install Path%]\FirstRun\WindowSWF\. Rename it to Communication Admin Console.swf.

The app_inspector.swf should already exist in this folder as Communication App Inspector.swf in the same folder; if not, copy the SWF file to the same folder. These applications will be available within Flash MX through the Window menu.

The Server Configuration Folder

This folder is very similar to a web server management console (see Figure 2.2). The configuration structure is located in the server-install folder (default: c:\Program Files\Macromedia\Flash Communication Server MX\conf\).

Figure 2.2. The Server Install folder (from C:\Program Files\) showing one adaptor with two virtual hosts.

This is meant only as a familiarization exercise; detailed explanation of this folder and how to use it is presented in Chapter 14, "Server Administration."

The folders below the conf folder represent server adaptors. Adaptors provide a security context to manage multiple Communication applications. By default, the server is installed with a single adaptor located in the _defaultRoot_folder. You can create additional adaptors by copying the _defaultRoot_ folder and editing the Server.xml file.

Warning

Create backups of the original XML files before you start editing them. These are important parts of the server, and if they become corrupt, you risk not being able to run your server. Editing these files should be done only by those familiar with XML. I also recommend that you review Chapter 14 before editing these files.

Within the adaptor folder (_defaultRoot_) are virtual host folders, which are declared in the Adaptor.xml file. In Figure 2.2, there are two virtual hosts defined in the root adaptor. Each virtual host must contain two configuration files: Application.xml and Vhost.xml. Like the Server.xml file, these files are very sensitive, and you should create backups before editing them.

The Flash Communication Server does not ship with any "console" way of managing this structure. You must edit these XML configuration files and folders "manually" using a text or XML editor. If you use Macromedia Dreamweaver MX, the XML configuration files will be color-coded with automatic code hints and code completion features to help you develop the files.


Servers and Access

A typical confusion when getting comfortable with the server is the distinction between the web server and the Communication Server. They are not the same thing nor are they accessed the same way. To compare, let's review a typical web server and how it references files, and then compare it to the Flash Communication Server.

A web server is typically accessed as http://www.myWebSite.com/.

If you have a web server installed on your workstation, you can also access it like this: http://localHost/.

Web servers are usually accessed with a web browser such as Netscape or Internet Explorer; however, Flash applications can also access a web server. Flash uses a web server to exchange static or dynamic content. The XML object, loadVariables, loadVars, getURL, NetServices, and loadMovie are some examples of Flash objects that require a web server to exchange data. Web servers return requested text or binary data to the caller using the HTTP or secure HTTPS protocol.

The Flash Communication Server is similar to a web server, but they are not the same. The most notable difference between the two servers is the protocol that is used. The Communication Server uses Macromedia's proprietary Real Time Messaging Protocol (RTMP) to handle requests. Right now, the only technology that can communicate using the protocol is Flash Player 6. You cannot access the Communication Server through a web browser.

Tip

Web servers and Communication Servers can co-exist on a single workstation or server. You can change what port numbers the Communication Server listens on by editing the conf\Server.xml file in the install folder for the Flash Communication Server. Remember to back up the configuration file before you change it!


The Authoring Environment: Macromedia Flash MX

Now that you have a good working knowledge of how the Communication Server is set up, let's review your authoring environment, Flash MX.

Flash MX is a fantastic authoring environment for both the design- and programming-oriented developer. Traditionally regarded as a "design" or "animation" tool, it is quickly being adopted by developers responsible for enterprise-level client/server applications. These applications are commonly referred to as rich media applications.

Flash MX is the authoring tool for the Flash Communication Server. As previously discussed, when you install the Communication Server on a computer with Flash MX already installed, add-ons are installed to Flash MX. Flash MX is outfitted with a special set of Flash Communication UI Components, a new Debugging tool, and an App Inspector tool. These three tools will help you build dynamic Flash Communication solutions. There will be an in-depth exploration of each new component in the next series of steps.

Flash MX uses two file formats. The authoring format is FLA and the compiled (published) format is SWF. The FLA stores authoring information about the application and allows you to edit that information in the Flash MX authoring environment.

The SWF file format is a format developed by a company called FutureWave and was acquired by Macromedia in 1997. The Macromedia Flash File Format (SWF) SDK is available freely from the Macromedia web site. The format is viewable in Flash Player 6 and can be compiled as an executable file independent of any additional resources. The process of "compile" is called publishing and is done within Flash MX.

Flash MX Authoring Environment

To build Communication applications, you need to have a basic understanding of the Flash MX authoring environment. Because Communication Server applications leverage new ActionScript objects, previous versions of Flash cannot be used to develop Communication applications. This book will assume you have a basic knowledge of the Flash MX environment and ActionScript. A great resource for Flash MX is the book Inside Flash MX by Jody Keating or Object-Oriented Programming with ActionScript by Branden Hall and Samuel Wan, both published by New Riders.

Flash MX is available for both the Mac and the PC. Communication applications can be developed and tested on both platforms. Mac developers must have access to a Windows-based server as there is no Communication Server available for Mac OS. To edit server-side scripts, access to the flashcom/applications folder is required. Because Flash movies (SWF) and HTML files are not required to be on the server, they can stay on the Mac OS file system. To install the Communication Server components in Flash MX, please review the sections in Chapter 1, "STEP 1: Installation and Setup."


The Testing Environment

Testing Flash Communication applications is very simple. You can perform testing on a single development machine (see Figure 2.3). However, it is strongly recommended that you test using more than one computer connected over a network. Applications supporting multi-way video and/or audio require that a web camera, microphone, and speakers are installed and working on each testing computer.

Figure 2.3. PC-only testing environment.

In the example of a basic testing environment shown in Figure 2.4, two Windows-based computers are used. Computer A is the development computer containing Flash MX and the Communication Server. Computer B is the remote client computer running a web browser with Flash Player 6 installed. Ensure that each computer can access the HTML and SWF files published by the developer computer. You can access either through a test web server or run the HTML/SWF file by opening it in a web browser (double-clicking usually works).

Figure 2.4. Mac OS/PC testing environment.

If you are developing on Mac OS, the setup will be a little different. Your Mac will be used to develop the Communication application and (possibly) serve the HTML/SWF file. The published HTML/SWF files must be accessible either through a Mac OS web server installed locally or through a network share. A Windows computer will be your second test machine. This computer will contain the Communication Server and a web browser with Flash Player 6 installed. In both situations, each computer has a web camera, microphone, and headphones attached. You can test your application on a single machine using multiple browser windows. Although this is possible, you may find conflicts when sharing multimedia resources such as your microphone or speakers.

Testing in Macromedia Flash MX

In both Mac and PC, test your application within Flash MX with the Test Movie (Ctrl+Enter) option; Mac OS uses Ctrl+Return. You can also use the Flash MX Debugger (Shift+F4) by running the Debug Movie command (Ctrl+Shift+Enter)(Mac OS uses Ctrl+Shift+Return) to enable the debug tools. Debugging a movie within Flash MX accesses the debug version of Flash Player 6, which interacts with the Flash MX authoring environment. This version of the player allows you to monitor any trace actions in the output window, interact with the standard Flash Debugger, or watch communication activity through the special NetConnection Debugger. It is important to test this way to ensure you are handling data properly and are communicating with any servers properly.

Debugging techniques will be covered in Chapter 12, "Client-Side (Flash) ActionScript."

Testing in a Browser

In both Mac and PC, you can test your application in a web browser using the embedded Flash Player 6. Although the debug and release versions of the player are the same, there are some differences in the player run-time between the Active X version (for Microsoft Internet Explorer) and the JAVA version (for Netscape). There are also differences between operating systems and devices.

To test your application within a browser, you must publish your application by clicking File, Publish or pressing Shift+F12. After you have published, you have two choices:

  • Web Server Access. Connect to the HTML or SWF file using an HTTP call to a local web server (http://localhost/flashcom/applications/myApp.html or http://remoteComputerName/flashcom/applications/myApp.html).

  • Direct File Access. Open the HTML file by connecting to it in your file system and double-clicking it. If you are accessing the file over a network (through Network Share or Apple Share), you need to ensure the correct operating system security is in place to access the files.


Summary

Now you have the basic server structure, and with your development environment set up, you are ready to start building some Communication applications.

The next two chapters will introduce you to some of the new UI components in Flash MX, and will show you how to set up an application on the server and monitor what is happening.


Chapter 3. STEP 3: Get Connected

Connecting to the Macromedia Flash Communication Server is extremely simple. In this chapter, you will not only connect, but also allow others to connect. You will set up the application on the Communication Server and watch as people try to communicate. In this chapter, we will review the App Inspector in detail and look at the NetConnection Debugger. We'll start at the server, and then move to Macromedia Flash MX, and finish back at the server. This round trip is just what you need to see the whole process.


Define Your Application on the Server

Defining your application on the server will be the most complex part of the whole process of getting connected. As you will see, it is not hard. Follow these steps:

  1. On your server, double-click My Computer and navigate to the flashcom\applications folder. (Default: c:\inetpub\wwwroot\flashcom\applications)

  2. Create a new folder within the applications folder called myFirstApp (see Figure 3.1).

    Figure 3.1. Create a new text document in the applications\myFirstApp folder.

  3. Open the new myFirstApp folder, right-click, and select New, Text Document. Name the new file main.asc.

  4. Open the new main.asc file in Windows Notepad or your favorite JavaScript or HTML editor. Macromedia Dreamweaver MX users can open this file in Dreamweaver MX to take advantage of code hints and color coding.

  5. Enter the following line of code:

    load("components.asc");

  6. Save and close the file.

There is one line of code, but it isn't that complex, and from this point forward, that is the only code you will need to get connected. The main.asc file will be explained in detail in Chapters 5, "STEP 5: Monitoring and Managing the Server," and 11, "Server-Side ActionScript (SSAS)." The components.asc file is the server-side counterpart used by the Flash Communication UI components. It is a library file that loads the UI framework and the UI component's SSAS ActionScript objects.

The application is now ready as far as the server is concerned. Now, let's build the user interface in Flash MX.


Build the User Interface in Macromedia Flash MX

If you haven't already done so, familiarize yourself with the Flash MX authoring environment (see Figure 3.2). In this series of chapters, you won't be getting into any advanced techniques; however, you should be familiar with the user interface, the timeline, and working with Flash UI components. The tutorials included with Flash MX are a good resource to learn the basics of the package.

Figure 3.2. Match your Flash MX environment to look similar to this.

In this exercise, you will create a simple Flash movie that will connect with the Communication Server and display a list of other people who have also connected. When finished, your Flash MX window should look like Figure 3.2.

SimpleConnect

The SimpleConnect component handles and maintains all server communication between the Flash player and the Flash Communication Server. SimpleConnect also provides a handy Login prompt for users to identify themselves. Using the SimpleConnect is easy. These next steps introduce you to the process of using the component in your applications:

  1. Open Flash MX and create a new movie. Save the movie (FLA file) in the flashcom/applications/myFirstApp/ folder. If you are working in Mac OS or not working directly on the development server, save the file in a working folder on your hard disk that is accessible by other computers.

  2. Open the Components panel by selecting Window, Components, or pressing Ctrl+F7.

  3. From the drop-down box, select Communication Components. If you do not see Communication Components in this drop-down, you need to manually install them. Review the section on manually installing Flash MX components in Chapter 1, in the section, "Communication UI Components."

  4. Drag the SimpleConnect component on to your Flash stage. The Flash stage is the white area in your workspace. The stage is what will be seen through Flash Player 6 when you publish this movie. You should see a hollow text box with a login button (see Figure 3.3).

    Figure 3.3. The SimpleConnect component on the Flash stage.

  5. With the SimpleConnect component selected, open the Properties panel (Window, Properties; or Ctrl+F3). Set the Application Directory to rtmp:/myFirstApp. There is only a single forward slash; it is not a typo. If you are connecting to a Communication Server that is not installed on your computer, you must enter a fully qualified host name, IP Address, or machine name of the server as follows (with a double slash after rtmp:):

rtmp://[computer name][:port]/myFirstApp

That's it for setting up the connection. It's really that simple. This SimpleConnect component takes away the need for any ActionScript to make connections. To leverage additional features, however, you may need to customize this component. Don't worry; for this exercise, that won't be necessary.

Note

Note the value myFirstApp. This is a direct reference to the folder you just created on the server in the applications folder. Notice how the applications folder was not declared here. This is because this folder is seen by the virtual host as the default folder for applications. It is mapped internally to the root of the Communication Server (in this case, localhost).

Adding the PeopleList Component

With the connection handled by SimpleConnect, let's add one more component that will let us see who is connected to the server. The PeopleList component displays a list of users who are currently logged into the server. Follow these steps to add the PeopleList component:

  1. From the Components panel, drag a PeopleList component to the Flash stage.

  2. With the new component selected, go to the Properties panel and assign it the instance name peopleList_mc.

With the component placed on the stage, you need to connect it to the Communication Server connection. This is done in the SimpleConnect component. Follow these steps:

  1. Select the SimpleConnect component on the stage again and double-click the [] next to Flash Com Components. A Values window appears, like the one in Figure 3.4.

    Figure 3.4. Add a new value, peopleList_mc, to the Values window of Flash Communication Components.

  2. Click the plus (+) sign. This creates a new row in the Values window. Double-click the default value and enter the instance name of the PeopleList component you just added—peopleList_mc—like what's shown in Figure 3.4.

  3. Click OK to close the Values window. The Properties window for the SimpleConnect should now look like what's shown in Figure 3.5.

    Figure 3.5. The Properties window for the SimpleConnect UI component.

Tip

Each Flash UI component connects to the SimpleConnect the same way. Declaring each instance name in the Flash Communication components list allows it to connect to the server. If you want to skip ahead, try placing a Chat UI component on the stage, giving it an instance name, and declaring it with the SimpleConnect. We will cover this in the next chapter.

Adding the ConnectionLight Component

ConnectionLight is a simple utility component that you have already seen in action. The Administration Console uses this component to show you when you are connected to the server. It will visually tell your users if they are connected. Add it by following these steps:

  1. From the Components panel, drag a ConnectionLight component to the Flash stage.

  2. With the new component selected, go to the Properties panel and assign it the instance name connectionLight_mc.

  3. Select the SimpleConnect component on the stage again and double-click [peopleList_mc] next to Flash Com Components. The Values window appears again.

  4. Click the plus (+) sign, and then enter the instance name of the ConnectionLight component you just added, connectionLight_mc.

The ConnectionLight changes color to yellow or red to illustrate a slow or closed connection with the Communication Server. Clicking on the component displays information about the local connection with the server. Details include the data latency rate and real time upload and download rates. It is a great tool to include in any Communication application.

That's it! You have just created your first Flash Communication application. Make sure that the SimpleConnect Properties panel looks like Figure 3.6. If you like, add in some simple user text prompts, using the Text tool, for your application (as shown in Figure 3.7). Now, let's test this movie and watch it connect. Don't forget to save your Flash file before you move on.

Figure 3.6. The Properties window for the SimpleConnect UI component should look like this before you test.

Figure 3.7. The myFirstApp.swf file running in the Flash MX debug player.
    [ Team LiB ]


Testing the Movie

If you are developing on the server, select Control, Test Movie in Flash MX. This compiles your movie to a SWF file and opens it in Flash Player 6 within Flash MX. Go ahead and log in with your name. After you click Login, you will see your name in the list shown in Figure 3.7.

If this does not work, here are some troubleshooting tips:

  • Ensure your Flash Communication Server is running by logging in to the administrator and pinging it. If it is not running, go to the Maintenance tab and click Start. You can also start the server through the Windows Start menu by selecting Programs, Macromedia Flash Communications Server MX, Start Service.

  • In Flash MX, ensure that the applications folder myFirstApp is correctly referenced in the Application Directory property of SimpleConnect.

  • In Flash MX, ensure that you have the peopleList_mc instance referenced in the SimpleConnect Properties panel.

  • Open the main.asc file on the server and make sure that the only line in it is load("component.asc");. If it is not, fix the error, and then restart the Communication Server. Note that each time you change the main.asc file, you must reload the application. Reloading applications properly will be covered in Chapter 5, "STEP 5: Monitoring and Managing the Server." For now, simply restart the service through your Administration Console.

  • If you chose an alternate install, you must ensure that the applications folder has access to the scriptLib folder. This will be discussed in detail in Chapter 14, "Server Administration." You can edit the application.xml file in the /conf/ folder to confirm the absolute location of the scriptLib folder.

Testing Remotely and on Mac OS

If you are working with Flash MX in Mac OS, or on a workstation separate from the server, you will need to change the SimpleConnect reference to the server. Make sure you are calling it by a fully qualified host name, IP address, or computer name as follows (see Figure 3.8):

rtmp://[IP Address][:port]/myFirstApp
Figure 3.8. The Properties panel for the simpleConnect component. Place the URI of your Flash Communication Server in the Application Directory property.

If more than one computer will be communicating with the server using this application (and there usually will be), you must declare the full server domain name or IP address in this field. You must also reference the server this way if you are using a Mac to develop the application.

Tip

To determine the domain name of your Windows server, contact your network administrator or do the following:

  1. From the Start, Programs, Accessories menu, open a command prompt.

  2. Enter IPCONFIG and note the IP address that is displayed.

    Note

    IP addresses starting in 192 or 127 or 10 (for example, 192.168.0.1) will not be accessible on the public Internet. These addresses are used for internal VPNs or LANs that might use a dynamic IP address range. If your testing computers are connected to the same network, you will be fine; however, if you want to have computers access your application outside your network, you may be required to reconfigure firewalls and ports. In this instance, your network administrator should be contacted.

  3. When you have your IP address or domain name, change the application folder to reference your server as follows:

    rtmp://[IP Address][:port]/myFirstApp

To use the name of your server for the connection, follow these steps:

  1. On the desktop, right-click My Computer.

  2. Select the Network Identification tab. Your Full Computer Name is displayed here.

  3. Change the application folder to reference your server as follows:

    rtmp://[Full Computer Name][:port]/myFirstApp

Now, take the test one step further by inviting another computer to connect (see Figure 3.9). Close the Flash player so that you return to Flash MX. To be certain that you have the IP address or computer name set in the SimpleConnect properties, select File, Publish (or press Ctrl+F12) to publish this application and generate an HTML file.

Figure 3.9. This example shows nine users connected using two computers.

On Computer A access the myFirstApp.html file and run it in a web browser. You should see your application running within the browser context. Log in to the application with your name.

On Computer B access the same myFirstApp.html file and run it within a web browser. You should see the first user in the PeopleList. Log in to the application using someone else's name (just don't tell them).

You should now see both names appear on the screen of both computers. Take the test one step further by adding a third user. On one of the computers, open a new browser window, with the HTML file loaded. Log in, and now you should see three users connected to the server.


What to Check if Your Application Is Not Working

If your application isn't working, go through this checklist to make sure you've covered these bases:

  • Is the Communication Server running and accessible by your workstation? (Can you run the example applications and log in to the Administration Console?)

  • Check your spelling. Ensure that the PeopleList component has an instance name (in its Property panel) of peopleList_mc and the ConnectionLight has a name of connectionLight_mc.

  • Ensure both of the instance names are registered with the SimpleConnect, Flash Communication Components parameter in the Properties panel.

  • Are you accessing your Communication Server properly in the SimpleConnect? If you are accessing the server locally on your computer, use rtmp:/myFirstApp/; remotely, use rtmp://192.168.0.2/myFirstApp/. The IP address should be the IP address of the server that is running Communication Server.

  • Does your main.asc file have the command load("components.asc");? Server code is case sensitive, so make sure this entire command is lowercase. If you changed the file, did you restart the server?

If you are still having problems, step through the exercise again slowly.


Summary

If you made it to this point, congratulations! As you can see, there are more components to a Flash Communication application than a standard Flash movie. As you get more familiar with the server and develop your own style of development, all of this will become easier. The hardest part is setting up the development environment and the testing phase. After contact has been made, things become easier.

Next up, we'll add a voice to the name, and even a live picture!


Chapter 4. STEP 4: Simple Chat and Video Conferencing

Lights, Camera, ACTION! I bet you would never have guessed that in only the fourth step, you would add live video, chat, and microphone support. You know all the basic concepts to make this work, still with no ActionScript. Building on the exercise you did in Chapter 3, "STEP 3: Get Connected," this chapter will expose you to the following four new Macromedia Flash UI components:

  • The Chat component enables live text chat.

  • The UserColor component allows you to change the color of your text in the Chat window.

  • The SetBandwidth component allows you to change the quality of video and audio incoming and outgoing streams relative to your connection speed.

  • Finally, the AVPresence component will enable your computer's video camera and microphone all within a Flash interface! This is a first for Flash—live video inside the Flash player. You can only do it with the Flash Communication Server.

Let's get started, first with the Chat component.


The Chat and UserColor Communication UI Components

Giving "Hello World" an entirely new identity, the Chat component quickly adds real-time text messaging to your Communication Server Application (see Figure 4.1). This exercise will build on the connection sample you built in the previous chapter. To add the Chat component, follow these steps:

  1. Open your previous example, myFirstApp, in the Macromedia Flash MX authoring environment. You should already have a SimpleConnect, a PeopleList, and a ConnectionLight already on the Flash stage.

  2. Drag a Chat UI component from the Components panel and place it on the stage.

  3. Name the Chat component chat_mc in the Properties panel. Remember, you must have the component selected to edit its properties.
Figure 4.1. The Chat UI component.

The Chat component has three elements to it:

  • The Message Input form

  • The Send button

  • The Message Display window

When you or other people enter a message in the text field (showing "Hello" in Figure 4.1) and press Send, everyone logged in will see your name followed by your message. You can scroll the archive of the message to view what was previously said.

When you are chatting, it is helpful to select a unique color with which to display your messages. This helps distinguish your messages from others. The UserColor UI component lets you select a color that will represent you in the Chat window (see Figure 4.2). Let's step through the process of using the UserColor component:

  1. Drag the UserColor component from the Components panel to an empty place on the stage.

  2. Name the component userColor_mc in the Properties window.
Figure 4.2. The UserColor UI component.

The UserColor component is simply a combo box that contains a series of color swatches. When a user selects a color, some Communication UI components will be visualized by this color.

Registering these two new components with SimpleConnect is the next step. This is done exactly as you did in Chapter 3, with the PeopleList component:

  1. Select the SimpleConnect component on the stage again and double-click the field that is now showing peopleList_mc, connectionLight_mc next to Flash Communication Components. The Values window appears as in Figure 4.3.

    Figure 4.3. The Values window of SimpleConnect.

  2. Click the plus (+) sign. This creates a new row in the Values window. Double-click the new row and enter the instance name of the Chat component you just added: chat_mc.

  3. Click the plus (+) sign again and add the userColor_mc instance to the list.

Your Values window should now look like what appears in Figure 4.3.

Your stage might be getting a little crowded now, so arrange and resize the components to look something like Figure 4.4. The components can be resized using the Free Transform tool on the Flash toolbar. Leave lots of room at the top because video is next.

Figure 4.4. Lay out your components to look like this so that you have room for video.

Test your new chat tool using Test Movie (select Control, Test Movie or press Ctrl+Enter). You should immediately see your name in the login box. If not, log in again. Go ahead and type something, but don't let anyone catch you talking to yourself.

When you are satisfied that it is working, leave the test movie running in Flash MX and load the myFirstApp.html file on Computer B. Log in, and you should see both users in the People list. Enter some messages, but be careful: If someone catches you doing this, who knows what they will think. It is recommended, at this point, to find a friend to help you test. It's going to get a lot more fun when you add the video cameras! Try out the color selector. Notice how it changes the color in the Chat window on your next message.

The UserColor component can contain customized colors; however, you will be forced to edit the ActionScript FCUserColor prototype. This is an advanced technique. There will be more discussion about customizing the UI components in Chapter 10, "STEP 10: Lobby Applications."

You might be thinking, "That's great, but what if I want to filter my chatty figs into their own rooms?" At this point, you should explore the Rooms UI component. Yes, Macromedia thought of that and gave it to you, but we will cover that later in Chapter 10. There are some advanced techniques required in ActionScript to make it work.

You might also find yourself pondering, "I like emoticons—those little happy faces you get by entering a colon and closing parentheses :)—but I don't see any emoticons included in the UI components." Well, you are on your own with that one. That UI component was not included in Macromedia Flash's UI component offering.

But first, on to video!


The AVPresence Communication UI Component

It never fails: If you show someone that you can chat with yourself, it gets a response of "That's cool." Then, you show someone a live video window and his whole perception changes.

The AVPresence UI component is a great tool to quickly see the bigger picture of the power this server offers. In this example, there will be three video windows:

  1. Drag three AVPresence UI components from the Components panel to the Flash stage, just below the SimpleConnect.

  2. Click on the first component and give it the instance name video1_mc in the Properties window. Each instance of the AVPresence must have a unique instance name.

  3. Enter instance names for the other two AVPresence UI components in their respective Property windows, video2_mc and video3_mc, respectively.

  4. Assign a unique value for the Presenter SharedObject property.

  5. Click the video1_mc AVPresence UI component. In the Properties window, click the av value next to the Presenter SharedObject. Give it the new value of av1. Do the same for the other two AVPresence UI components, giving them values of av2 and av3, respectively. This step ensures the video streams will be attached to the proper AVComponent. If you don't do this, you may see your video camera in every window that is enabled.


The SetBandwidth Communication UI Component

Now that the Video objects are ready, we're going to add one more UI component to control the quality of the video. The SetBandwidth component lets the user optimize the quality of the camera and microphone streams by defining the bandwidth that is available to them. There are three preset bandwidth settings (LAN, DSL, and MODEM) that you can edit in the Properties window. These names make reference to the upload and download speeds available to you. There is also a custom setting that lets the user tweak the bandwidth.

Selecting a Modem setting allows (by default) a 33 kilobit per second (kBps) stream to be received and a 33kBps stream to be sent over the connection. Let's step through the process of adding the SetBandwidth UI component:

  1. Drag a SetBandwidth UI component from the Components panel to the stage.

  2. Name it bandwidth_mc in its Properties panel.

  3. Select the SimpleConnect box, and then add these three new video components and the bandwidth component to the list of Flash Communication Components. When you are finished, the Values window should now look like Figure 4.5.

    Figure 4.5. Your SimpleConnect Values window should now contain all the video components.

When you are ready to test the application, make sure your multimedia gear is plugged in, installed, and working. It is a good idea to turn down your speakers or headphones before you launch this application. If your testing environment has microphones and speakers too close together, you will get audio feedback. You should also make sure your camera is not being used by another application (like the Yahoo! Messenger). If it is, the Flash player will not be able to connect with it.

When ready, select Control, Test Movie. Log into the application. You will see the three video windows you placed on the stage, but no video will appear (see Figure 4.6).

Figure 4.6. The AVPresence component waiting for a user to publish to it.

Each AVPresence component requires a user to select a video window to publish to. When you click on a window, the Flash player displays a privacy window requesting permission to access your camera and microphone.

This always happens when any Flash movie tries to access these devices. Macromedia has placed this privacy feature directly into Flash Player 6 to ensure your privacy is protected (see Figure 4.7). There will be more detail on this window and how you can manage it in Chapter 12, "Client-Side (Flash) ActionScript."

Figure 4.7. The Flash player Privacy window.

Click Allow at this prompt to continue.

Your camera and microphone will now be enabled, and you should immediately see yourself, or whatever your camera is pointing at, in the AVPresence window. If your microphone is connected, talk into it. You should see the Flash Audio meter registering your voice.

On Computer B, have a friend access the application and enable its video camera and microphone. At this point, you should see through each camera on each computer, just like Figure 4.8. With your microphones, you should now hear each other through the speakers or headphones.

Figure 4.8. The myFirstApp Communication Application showing two video sources and a great conversation.

If you are having sound problems such as feedback or no sound, check all your connections and make sure your windows volume control is set properly. You can also adjust your microphone and other settings by right-clicking on the Flash Application (Mac OS: Ctrl+click). Select the Microphone tab. Chapter 12 will explain all settings that can be controlled with Flash Player 6.

The AVPresence component has other features including the capability to pause video feed and mute audio feed. Roll over the video window that contains your video feed (see Figure 4.9).

Figure 4.9. Icons appear when you roll over the window of your camera. These icons stop the publishing stream, muting your presence to everyone.

Note

A note about the streams: Each AVPresence component consumes a one-way stream. If all three video windows are being used, each Flash player will be handling three streams in total. If you are sending (or publishing) your stream, you only consume one stream. There is no limit to the number of streams you can have per Communication Server. Your only limitation is bandwidth. For example, 3 streams at DSL speed (256/kBps) would consume 768kBps (3x256) or three-quarters of 1MB. Understanding the bandwidth available to you is very important.

When you do this, you will see three icons within that window:

  • The (x) icon stops publishing your video feed and frees up the AVPresence component for another user to connect.

  • The Camera icon pauses your video publishing, but still allows you to transmit audio. This means that everyone connected will see a still "snapshot" of the last frame captured.

  • The Microphone icon mutes your audio. These icons directly affect the publication of your stream and affect everyone receiving the stream. Muting your microphone does not affect your video feed.

On Computer B, use your mouse to roll over the Video window showing someone else's video. Two icons will appear, the Camera icon and the Microphone icon. Click these icons to pause receiving their video feed or mute their audio feed. Either of these icons will only affect the stream coming to your computer; it will not have an affect on the publisher nor anyone else connected. Other people in the communication will retain their live feeds.


Summary

You are only on Chapter 4, and you think you have experienced everything the Flash Communication Server can do? Clearly, it can do a lot more than synchronize chat and video feeds. The next chapter will step out of the development process and take a look at what is happening on the server, introducing you to the Administration Console, the App Inspector, and the NetConnection Debugger. Chapter 6, "STEP 6: ActionScript with NetConnection()," will resume our exercises with the introduction of ActionScript.


Chapter 5. STEP 5: Monitoring and Managing the Server

Macromedia Flash Communication Server MX is shipped with three tools to help monitor and manage load, connections, and applications. These tools are Macromedia Flash-based applications built by Macromedia. For this chapter, you will get familiar with the pre-built applications and integrate them into the development environment. We will use the example built in the previous chapter as our test application.

Tip

Communication Server ships with a Server Management ActionScript Dictionary that describes the application programming interface (API). The API is the foundation to create (or integrate) custom administration modules, or to build on top of the existing Administration Console shipped with the product. As a working example, you can download the source ADMIN.FLA file from Macromedia, but you have to own a registered license of the product before the company will let you have it.


What Happens When You Run Your Flash Communication Server MX Application?

A communication application run for the first time creates an application instance on the server. In Chapter 3, "STEP 3: Get Connected," you created the myFirstApp folder within the flashcom/applications folder; this is your starting point. This folder provides the server with a location to store its resources that are persistent in your application. These persistent resources can include SharedObjects or recorded video. SharedObjects store data such as chat logs, connection information, or database information. The folder is also a location to store any recorded video your application requires. The folder should be considered a collection of resources the server needs for an application.

The application instance is stored in server memory and is created when an application first runs or is manually "instanced" through the App Inspector. On first execution, the server executes the file main.asc or a file matching the name of the application. In our example, the server looked to run main.asc; if that had not been found, it then would have looked for a file called myFirstApp.asc. It is your decision how you want to name your initial file. There is really no benefit for using one or the other.

These files contain server-side ActionScript (SSAS). ActionScript methods and objects required for the successful operation of a communication application are declared in these files. The server reads this file and parses it through its ActionScript interpreter storing the functions in memory and executing any commands. ASC files are, in essence, compiled (or published) into the server RAM.

The main.asc file you created contained a single ActionScript command:

load("components.asc");

This command loaded a series of server-side objects required by your myFirstApp movie. The objects included the ActionScript objects used by the Communication UI components. You actually see them load when you explore the App Inspector. Flash components, like SimpleConnect, Chat, and AVPresence, had their server-side counterpart scripts loaded into server memory, ready to be accessed by any Flash Player 6 loaded with your application. The components.asc file can be viewed from the flashcomm/ScriptLib folder. The ScriptLib folder is a special folder that has a virtual mapping inside your application. Chapter 14, "Server Administration," will review the uniqueness of the ScriptLib folder.

Any changes made to server-side (ASC) files require the application to be reloaded. The reload process is important to become familiar with after you start developing server-side ActionScript. The Administration Console and the App Inspector will help you manage and monitor these application instances. They also provide tools for loading and unloading the applications.


ADMIN Component: Administration Console

The Administration Console is a Flash application shipped with the Communication Server to help you manage and monitor the server. It runs within Flash Player 6 and uses the Server Management API to communicate with the server. The Server Management API is a powerful program interface used to manage the server through ActionScript.

For this chapter, we will manage the server using the pre-built Administration Console running within Flash Player 6. Locate the file admin.swf in your flashcom/admin folder and double-click it to launch it. The console operates exactly the same as if it was running embedded within the HTML frameset: flashcom/admin/admin.html.

Note

The Administration Console manages server configuration, XML files located in the [%FLASH COMMUNICATION SERVER INSTALL PATH%]\conf folder. This folder and its contents must have read/write access before attempting to change server settings. These files will be explored in detail in Chapter 14, "Server Administration."

Logging into the Administration Console

The Administration Console communicates on port 1111 by default (see Figure 5.1). Accessing the server through a firewall requires your network administrator to ensure the port is open. Administering a communication server from a remote computer requires the fully qualified host name (FQHN) and, if required, alternate port number in the Host field. The following are host connection string examples:

  • HOST: localhost Access a communication server located on the local computer.

  • HOST: 192.168.0.158 Access a remote (or local) server within a virtual private network (VPN), DHCP, or local area network (LAN).

  • HOST: myComputerName Access a remote (or local) server by computer identification name within a VPN, DHCP, or local area network.

  • HOST: http://flashComm.MyDomain.com Access a remote server by FQHN from outside a LAN or from outside a physical network.

  • HOST: http://www.MyDomain.com:1234 Access a remote server by FQHN from outside a LAN or from outside a physical network with a custom port number.

Figure 5.1. The Administration Console's login screen, viewed in Flash Player 6.

In writing this book, I assume your server is installed on the localhost computer. Enter the proper host, login name, and password you supplied the server during the installation process, and then press the Connect button.

The connection light turns green and, when you have logged in successfully, you enter the full Administration Console, seen in Figure 5.2. The bottom of the Flash player window can stretch to give you more screen space as you need it.

Figure 5.2. This host is displaying four applications that have been run. (To display the applications on your server, click the Update button.)

You have just logged in as the default Server Administration user. Two types of administration users are supported by the Communication Server:

  • The Server Administration

  • The Virtual Host Administration

Two principle differences exist between the administration levels. First, server administrators have the control to start and stop any application instances across any virtual host. The virtual host administrator can only manage application instances within his assigned virtual host. Server service control can be managed by a server administration, meaning the user can stop, restart, or halt the server. The virtual host administration does not have that right.

The default server administration user will be used to keep things simple. Chapter 14 will cover server administration and user roles in a larger context.

The Administration Console has five primary screens:

  • Diagnostic

  • Maintenance

  • Admin Users

  • Live Log

  • License

You access these screens through the tab interface at the top. Each panel will be explored separately.

The Diagnostic Panel

Click the Update button when you arrive at the Diagnostic panel. The history and current state of each application that was loaded or unloaded is displayed when Update is clicked. The length of time the Communication Server service has been running (uptime) is displayed among other items in the upper bar. In Figure 5.1, you can see this server has been online for 1 day, 1 hour, and 1 minute.

Every application related to this server is displayed for server administration level users. Virtual host administrators will only see applications they have control over within their virtual host.

The Ping button calculates the time (in milliseconds) for the server to respond and display the information. In Figure 5.2, it took 20ms for the server to respond. This is a great tool to use to determine the speed of your server. Response time is affected by network speed and the server processor speed.

The Maintenance Panel

The Maintenance panel provides a convenient interface for managing application instances, virtual hosts, and the server (see Figure 5.3).

Figure 5.3. The Maintenance panel within the Administration Console.

Applications

All active application instances currently running on the server are displayed in a drop-down menu. The menu updates itself when a new application is instanced; however, if you have it selected, or pulled down, it does not update. Selecting a running application instance allows you to reload it, unload it, or remove it. Reloading or unloading is necessary only if you change any ASC files. This process closes the connection to any user who is connected to it, forcing them to reconnect.

Warning

Use the Remove button with extreme caution. It not only stops the application, but also deletes (with no undo) your entire application folder. There is no reason you should use the Remove button if you have access to the server.

Adaptor/VHost

If more than one virtual host is running on the server, this option manually starts/restarts or stops it. Simply enter the host name and the virtual host name separated by a forward slash (/) and click the Start button. Stopping or restarting a virtual host closes the connection between every user on every application running within that virtual host. If you are logged in as a virtual host administrator, you do not have the rights to connect with other virtual hosts, and this control will be masked out.

Server

Server commands allow you to stop, start, or halt the server service. The difference between a server halt and a server stop is that a Stop command will tell the server to cleanly shutdown all running applications, clearing any temporary files. The stop also closes any streams and shared objects that are in use. Halt just stops the server with no clean up. If practical, you should also use the Stop command, reserving a halt for extreme circumstances. Consider the difference between halt and stop as pulling the plug on your computer versus using the shutdown sequence. Two very different ways to shut something down, but ultimately the same result. It's the consequences you will have to deal with later that you should be concerned about.

The Admin Users Panel

The Admin Users panel is the Communication Server access controller (see Figure 5.4). Server administrators and virtual host administrators can be added within the context of this panel. Each user has rights to access the Administration Console and the App Inspector. The virtual host administration users will be limited to managing only the virtual host they are assigned to. This includes monitoring application details and restarting the virtual host. Virtual host administrators can create additional users, but only for their host.

Figure 5.4. The Admin Users panel within the Administration Console.

Administrator accounts cannot be assigned to more than one virtual host. There is no capability to create application-level users for this version of the Flash Communication Server. If you are planning to deploy the Communication Server as a shared hosting facility, you must create a virtual host for each account to ensure security.

There are four activities within the Admin Users panel:

  • To add a server user, select the Server folder, enter the new user login name and password with confirmation in the three fields, and then click the Update/Add button.

  • To add a virtual host user, select the virtual host, enter the new user login name and password with confirmation in the three fields, and then click the Update/Add button.

  • To remove any user, click the username, and then click the Remove button that appears.

  • To change any user's name or password, click the username, change the information, and then press the Update/Add button that appears.

The Live Log Panel

The Live Log panel is only available if you are logged in as a server administration user (see Figure 5.5). Virtual host administrators access a similar live log tool in the App Inspector to monitor specific activity for an application. This tool allows you to watch access connections, disconnections, and system errors that might occur. To clear the window, press the Clear Window button.

Figure 5.5. The Live Log panel within the Administration Console.

The License Panel

The License panel displays information about the server version, category, and edition. In particular, this window displays license limitations. In Figure 5.6, you see the trial license is a professional version, with a maximum of 500 simultaneous users and a maximum bandwidth of 10mbps.

Figure 5.6. The License panel within the Administration Console.

The Communication Server license is a scalable license. Administrators can purchase Capacity Packs from Macromedia to increase the number of simultaneous or "peak" users and increase bandwidth. To purchase these packs, visit http://www.macromedia.com/software/flashcomm/.


Developer Component: Communication App Inspector

When you are ready to tackle server-side scripting, the Communication Server's App Inspector will be your new best friend. The App Inspector is a view into the server from within the Flash authoring environment. It is one of the three tools you can use when you are debugging. The App Inspector operates similarly to the Flash MX Output window displaying compiler errors and trace activity at runtime. It also lets you monitor SharedObject connections and streams being sent or received. You need this tool to recompile (reload) your application when changes are made to the main.asc file.

If you had Flash MX installed on your computer before you installed the Flash Communication Server, you are ready to open the Inspector. If you are working on Mac OS, or on a computer that is remote from the server, you will have to install the Inspector manually. Please refer to Chapter 1, "STEP 1: Installation and Setup," to learn how to install it manually. You can also access the Inspector from within the Communication Server Administration Console.

The App Inspector presents you with the familiar login screen. Log in with your server host, name, and administration password. The virtual host password assigned to you by your system administrator can also be entered here. The familiar connection light will turn green; and if your login was successful, you will be pushed to the Application Instances panel.

Application Instances Panel

The Application Instances panel is the first screen you see after you have logged in successfully (see Figure 5.7). The instances window immediately displays every loaded application. If you are using a virtual host account, only the applications within your host are displayed. Server administration logins will see every application from every host.

Figure 5.7. Application Instances panel in the Communication App Inspector.

This panel is the only panel that gives you some interaction with your application. From this panel, you can load and unload applications. It also acts as an application browser displaying each running application on the server.

If you do not see any application instances in the window, you can load one. Let's practice loading and unloading application instances using this panel.

Loading an Application Using the Macromedia Flash Communication Server MX App Inspector

If you completed the previous exercises using the application myFirstApp, use that as your example. If not, use a sample application installed with your server called sample_broadcast. Follow these steps to load the application:

  1. Select the myFirstApp/_definst_ instance in the Instance window, and then click the Unload button.

  2. Type myFirstApp in the App/Inst text box and click the Load button.

    Notice that the application, myFirstApp, now appears (again) in the Instances window. An instance of the application called _definst_ has been automatically created for the myFirstApp application. The name _definst_ is simply the default name for an undefined instance. All applications that use the SimpleConnect method, as myFirstApp does, always use the default instance name. You may require additional instances as your applications expand. ActionScript normally controls the instances, but for demonstration purposes, let's create a couple new instances.

  3. Type myFirstApp/myInstance in the App/Inst box and click the Load button.

    Notice that there are now two instances of myFirstApp running on the server. Now, try to load an application that doesn't exist.

  4. Type mySecondApp in the App/Inst box and click the Load button.

    The App Inspector returns an error. A folder on the server within the applications directory called mySecondApp is all you need to create an instance. Let's do one more test before moving on.

  5. Unload every instance of myFirstApp in the instances window by selecting each instance and clicking Unload.

  6. Load the example myFirstApp.fla into Flash MX.

  7. Test the movie by selecting Control, Test Movie, but make sure you have the App Inspector open.

Keep your eye on the Instance window. In about 10 seconds, you should see a new instance of myFirstApp appear. Application instances automatically are created by the first Flash player to run an application if it is not already running.

Normally, this is not a process you would follow, but it is good to understand how application instances are created, and how the App Inspector can help manage them.

Let's move on. With the new instance of myFirstApp selected, click the View Detail button. The statistical details relating to that application instance open. There are four areas of monitoring within this Inspector: Live Log, Streams, Shared Objects, and Statistics.

The Live Log Panel

The Live Log panel is similar to the Live Logs you saw in the Administration Console (see Figure 5.8). Specific information about the application's instance is displayed here. The Administration Console log displays information about system-wide communications and connections.

Figure 5.8. The Live Log panel.

When this panel is open, it streams live stats about the application. When a user starts her web camera, for example, the server starts a NetStream. This is represented in Figure 5.8.

Three buttons are available above the panel:

  • Disconnect. Logs you out of the App Inspector completely.

  • Change App. Returns you to the previous screen.

  • Reload App. Disconnects all users running the application and reestablishes a new instance of the application. By clicking this button, any server-side (ASC) script trace messages appear.

These buttons will always appear at the top of the App Inspector.

The Streams Panel

Figure 5.9 displays the log for the _definst_ instance of myFirstApp. The instance currently has two connected users and one AVPresence (camera) window open. This can be determined because only a single publisher is displayed, meaning only one user is transmitting. The two playing live streams show that two users (including the user who is publishing) are watching the live video stream. In this example, you can identify unique users by the ClientID declaration.

Figure 5.9. The Streams Monitor displaying stream details for the myFirstApp/_definst_ application instance.

This tool will come in handy particularly when debugging advanced applications where you have more control over the streams using ActionScript. There will be more explanation about the NetStream object in Chapter 7, "Streaming Video with NetStream()."

The Shared Objects Panel

SharedObjects are a cornerstone of the Communication Server. In concept, they are similar to the local SharedObject model in Flash MX; however, with the Communication Server, SharedObjects can also be created at the server by the server or through ActionScript. Their persistence can be either temporary or stored, as represented in Figure 5.10.

Figure 5.10. The Shared Objects Monitor.

These objects allow your Communication Server applications to share data, such as database information, or the position of a shared cursor. The Chat window used in the myFirstApp exercise is a great example of a persistent server-side SharedObject. The data in the Chat window is made available by accessing the shared chat object on the server. Each Flash client that connects with the server accesses that data object to return the chat text.

This monitor displays both the persistent (stored) and temporary SharedObjects used by an application instance.

The Statistics Panel

The Statistics panel displays the overall state of an application's instance (see Figure 5.11). This is helpful for tracking an instance's server resource consumption (RAM, processor, and so on). If you are running out of connections, or bandwidth, you can determine if this application instance is responsible and take the appropriate action. As you get more advanced, you will find this tool helpful for optimizing application performance.

Figure 5.11. The Statistics panel.

The number of Accepted or Rejected users, the application running time (Uptime), and when it was first instanced (Launch Time) are also displayed here. Bandwidth information displays bytes that the server has received and sent. In Figure 5.11 you can see there have been 5,298 bytes (or 5k) of data sent to the server, with 10,741 bytes (or 11k) of data sent from the server. Why is it double? There were two users connected. The server received a transmission (or publishing) stream from one computer and sent it out to two computers.

The Messages per Second statistic operates similar to the bandwidth display. One computer sends a message, and the server broadcasts it to every connected user (including the publisher). A collected total of three messages were sent by the users. The server delivered two copies of each message—one for each user—thus, the server shows seven messages out. Messages also include exchanges between client and server such as an ActionScript command informing the client to start playing a new video stream.

Messages Dropped does not represent scripting command messages lost, but if a user disconnects and the message could not be delivered, it is recorded in this count. Drops also occur if a connected client falls behind in receiving data as a result of its local connection, computer speed, or the stability of the Flash application.

The Statistics panel updates itself every 15 seconds.

App Inspector Summary

This tool will become an invaluable asset to the development of Communication Server applications. When using the SimpleConnect methods, as we have in the examples so far, you do lose some control of your application. This book will make reference to the App Inspector periodically, to monitor and debug some advanced scripting development.

The third and final tool that Macromedia has shipped with the Communication Server is the NetConnection Debugger. The debugger allows you to watch ActionScript objects being sent between the server and the client. If you have used Flash Remoting MX, you will be familiar with the debugger. It is also used to monitor Action Message Format (AMF) exchanges when communicating with application servers such as Macromedia ColdFusion MX, Microsoft ASP.NET, or any Flash Remoting MX-enabled J2EE server. It is used to closely monitor AMF messages, server function invocations, and responses. It, like the App Inspector, is not an interactive debugging tool; its only purpose is to "watch" activity.


Developer Component: NetConnection Debugger

Before you can use the NetConnection Debugger, you must add a single line of ActionScript to your application (see Figure 5.12). This single line of code adds the required class files to your Flash application to enable the NetConnection Debugger.

Figure 5.12. Adding the NetDebug class files to your Flash application using ActionScript.

To add the class files, follow these steps in the Flash MX authoring environment:

  1. Open your Communication application (myFirstApp.fla) in the Flash MX authoring environment.

  2. Open the Actions panel by selecting Window, Actions (or press F9).

  3. Turn the Actions panel into Expert mode by pressing Ctrl+Shift+E. This allows you to manually add the line of script to your application.

  4. Click the First Frame in the first layer of your movie (or a specified Actions layer that you may have set up) and enter the following line of code in the Actions panel:

    #include "NetDebug.as";

  5. Open the NetConnection Debugger in Flash MX by selecting Window, NetConnectionDebugger.

  6. Test your communications movie in Flash MX by selecting Control, Test Movie or pressing Ctrl+Enter.

When the movie runs, the NetConnection Debugger begins to display numerous events on the left side of the panel. This is the Flash player communicating with the server.

The NetDebug.as file was installed in the \Macromedia\Flash MX\Configuration\Include\folder. Any files placed in this folder can be included into Flash MX without specifying a directory path. When engaged, the NetConnection Debugger monitors any AMF activity on your computer. This is helpful if you need to watch exchanges between two Flash players open outside Flash MX (including applications running within a web browser).

Take a moment and scroll through the list of events. The debugger is not interactive, meaning that you cannot affect your movie with anything you do in this panel. To view expanded details, click the Details tab on the right side. Figure 5.13 displays detail of the first Communication Server event, Connect, originating from the Flash player.

Figure 5.13. The NetConnection Debugger in action. Filters and preference can be displayed by clicking the Filters and Preferences arrows.

Warning

Tracking problems you might have in your code, or trying to sort out unusual server behaviors, will be easier with this tool. The NetDebug class files are not required and should be commented out when you are ready to deploy your application to a production server. The file will add unnecessary file size to your SWF movie.


Summary

The three consoles included with the Communication Server are very useful for monitoring your application and tracking what is happening. In the chapters following, use these tools to help you debug your server-side ActionScript and monitor what is going on with your applications. Flash MX comes with a fantastic interactive debugger. You should read up in the manuals on how to use it. Debugging will be covered in depth in Chapters 11, "Server-Side ActionScript (SSAS)," and 12, "Client-Side (Flash) ActionScript."


Chapter 6. STEP 6: ActionScript with NetConnection()

Not only are Communication UI components fantastic tools for building applications quickly, they are also great tools for teaching how the Macromedia Flash Communication Server operates. The full power of the technology lies within Flash's scripting language, ActionScript. The next five chapters will combine the use of the UI components with ActionScript and some home-grown techniques both inside Macromedia Flash MX and on the server.

If you have done any work in object-oriented programming languages, Flash ActionScript should seem familiar. The invocation of ActionScript is the same as that of JavaScript; and, like JavaScript, it is founded on the ECMAScript-262 specification so it operates and behaves as you would expect JavaScript would. On the server, ActionScript behaves like Server-Side JavaScript 1.5 (SSJS) as implemented by Netscape's Enterprise Server. Chapter 15, "Communication Application Architecture Strategies," has more details on ECMAScript and Netscape. If you are not familiar with programming languages, don't worry; these next few steps are designed to walk you through the steps slowly with plenty of description about what is going on.


The ActionScript Editor—a Primer

The ActionScript Editor in Flash MX has come a long way since it was first introduced. Access it by pressing F9 or selecting Window, Actions. There are two modes to the editor: Normal mode and Expert mode. Normal mode uses a wizard-type approach for writing ActionScript and does not allow you to directly edit the ActionScript by hand, whereas Expert mode does. Coding will be the focus in these chapters, so you should be in Expert mode to follow along (see Figure 6.1).

Figure 6.1. The properties of the ActionScript panel can be accessed by clicking the icon in the upper-right corner of the panel, just below the Close button. Placing the ActionScript Editor in Expert mode allows you to edit ActionScript.

Note

Enter Expert mode by clicking the Actions panel to bring it to focus and pressing Ctrl+Shift+E. Alternatively, you can use the Properties menu, located on the upper-right corner of the panel.

Turning on View Line Numbers will help you when debugging your code. Flash MX notifies you of scripting errors by referencing the Frame, Layer, and Line Number. Line numbering can be enabled by pressing Ctrl+Shift+L or selecting View Line Numbers from the panel Properties menu.

Programmers learning Flash for the first time are often confused by the Timeline. These next five chapters will work exclusively on Layer 1 in Frame 1. You will know ActionScript is contained within this frame when the letter "a" appears in the frame, as seen in Figure 6.2.

Figure 6.2. ActionScript located within a frame displays a letter "a" above the keyframe circle. This example shows ActionScript located in Frame 1 of Layer 1 with an empty keyframe.

Code hints like those found in Homesite, Macromedia Dreamweaver, or DMX are a great new part of the ActionScript Editor (see Figure 6.3). They are displayed as you type code into the editor. To get the most out of the code hints, use special suffixes on your object names. For example, if a MovieClip instance is on the stage, naming it myClip_mc enables the code hints for the MovieClip object to appear. The _mc is what the editor senses. Reference to these code hint suffixes will be mentioned through this book. When using object methods, code hints display the required and optional parameters. A full list of code hints is presented in Chapter 12, "Client-Side (Flash) ActionScript," in the "Code Hints" section.

Figure 6.3. Code hints are triggered in the ActionScript Editor when entering code. Hints are triggered by keywords or strings. In this example, "Camera" is a keyword that opens the Camera code hint.

The Actions panel is a handy guide to access and reference the properties, methods, and events of every Flash MX object. When you install the Communication Server authoring components, a new book called "communications" appears. Take a few moments to look through the new objects you now have control over. There is also full documentation on each object installed in the Reference Panel (Shift+F1). Appendix B,"Flash ActionScript Objects Quick Reference," contains a full list of each object.

SharedObject and LocalConnection are also included in the communications book. These two objects are native objects in Flash MX but their Actions panel entry was excluded in the original release. The Communication Server does not use LocalConnection; however, it has extended the native function of the SharedObject. SharedObjects will be discussed in Chapter 8, "STEP 8: Collaboration with SharedObject()." All communication objects excluding NetConnection and NetStream can be used without the Flash Communication Server. However, it wouldn't be too much fun watching yourself or talking with yourself, now would it?

Located on the left side of the editor, the ActionScript panel can be closed and opened quickly to give you more editor space (see Figure 6.4). Just click the arrow in the separator bar, and the panel closes. If you are new to ActionScript, you can drag any function or property from the list inside the panel to the editor.

Figure 6.4. The ActionScript panel contains the Communication object library. This is installed with the Communication Server.

Flash MX cannot be used to develop server-side ActionScript (SSAS). Editing this code (inside the main.asc file) does not require anything fancy, a simple text editor will do the trick; however, simple color-coding will help you in your development. JavaScript editors work perfectly to edit this code. Macromedia has included support (color coding and code hints) for ActionScript in its Dreamweaver MX product. This book uses Dreamweaver MX to edit server-side ActionScript.

Tip

Code hints for server-side ActionScript are included within Dreamweaver MX. Server configuration XML files also have code hints available when you edit them in Dreamweaver. Try it out by opening Server.xml inside Dreamweaver MX and entering an XML tag used in the Server.xml file.

Now that you have been introduced to the ActionScript Editor and have reviewed some of the new objects available, let's jump into the code with both feet. Establishing a connection to the Communication Server using the NetConnection() object will be your first task.


The NetConnection() Object

Flash Player 6 connects with the Flash Communication Server using the NetConnection() object. The NetConnection() object maintains persistent connection using the Real Time Messaging Protocol (RTMP). It is defined by Macromedia as "the object that manages multi-directional communication between the Flash Communication Server and Flash Remoting MX servers." Think of the NetConnection like a tunnel between the client and server. The tunnel can facilitate the transmission of multiple one-way streams or ActionScript objects coded in Action Message Format (AMF). It is the only two-way connection possible between client and server. The NetConnection() object cannot establish a connection between two Flash players; for that functionality, you can use the LocalConnection object.


NetConnection() Methods, Properties, and Events

If you are not familiar with programming, it is important to understand that every object has three components. Object methods (or behaviors) are internal functions that affect the property (or characteristic) of an object. For example, in a movieClip, the method .gotoAndPlay() affects the MovieClip property _currentFrame. Properties (or characteristics) are variables that contain values describing an object. For example, a MovieClip on the Flash stage has _x and _y properties. The values of _x and _y are numbers representing the x and y position of the MovieClip. Most properties can read or be written to. For example, a MovieClip can be repositioned by changing the value of the _x and _y properties. Some properties are read-only, such as the _currentFrame property.

Events act as listeners that respond to actions or inputs affecting the object. For example, when you move your mouse over a button, you trigger an onMouseOver event. Events must be overwritten. That means no default (prototype) actions are associated with an event. You are responsible for creating event actions by overwriting the default event handler. Consider the onMouseOver event. You can script a sound effect to play when the user rolls over the button triggering the onMouseOver event. The NetConnection() methods are as follows:

  • .connect() Establishes the connection between client and server. On the server, this method is handled by the Application.onConnect() event.

  • .close() Disconnects the connection between client and server. On the server, this method is handled by the Application.onDisconnect() event.

  • .call() Invokes a server method defined within the application. Methods are defined with the main.asc file.

The NetConnection properties are as follows:

  • .IsConnected Returns a true or false. It is affected by the connect()and close() methods.

  • .uri Returns the Uniform Resource Indicator connection string used in the connection. This is used to easily access the correctly formatted value.

The NetConnection event is onStatus. This event is called to handle server status changes. Status changes include errors, connects, and disconnects.

Full details of the NetConnection object are listed in Appendix A,"Server-Side Objects Quick Reference."

Why would you even bother using ActionScript to connect, when there is a simple UI component (SimpleConnect) that will do it all for you? The answer is simple: control. Using ActionScript to manage your communication with the server allows you to leverage the server in ways that are just not possible with the SimpleConnect component.

Controlling the data flow, sending messages, accessing a database, streaming video, or controlling a live broadcast or networked video game cannot be done without the use of ActionScript. Exercise 6.1 will introduce you to using ActionScript to connect with the Flash Communication Server.

Exercise 6.1: Get Connected with ActionScript and NetConnection()

This exercise establishes a connection using ActionScript using the Communication UI components without SimpleConnect. Before coding, there are two things you need to do. First, set up a new application folder on the server; then create a new movie and add a couple UI components to your movie:

  1. Create the application folder on the server in the /flashcom/applications/folder. Call it mySecondApp.

  2. Copy the main.asc file from your previous example into the new mySecondApp folder. If you want to create a new main.asc file, make sure the following line of code is included:

    load("components.asc");

  3. In Flash MX, place a ConnectionLight and a PeopleList UI component on the Flash stage.

  4. Select the ConnectionLight and give it the instance name of connectionLight_mc in the Properties panel. This gives you some visual feedback when a successful connection has been established with the server. Give the PeopleList component the instance name of peopleList_mc.

Now you are ready to start coding.

Connecting Communication Server using ActionScript is pretty simple. Not quite as simple as the SimpleConnect UI component, but simple none the less. With the Flash ActionScript Editor open (F9) and set to Expert mode (Ctrl+Shift+E), follow these steps:

  1. Enable the NetConnection Debugger by including the NetDebug class files. Add the following line of code to Frame 1 on Layer 1:

    // Include the Debug Class file
#include "NetDebug.as"

  2. Create an instance of the NetConnection object. If you are new to coding, this procedure copies all the methods, properties, and events defined inside the NetConnection prototype. This instance (or copy) of NetConnection is called myConnection_nc. Notice the _nc suffix. This triggers the NetConnection code hints when it is typed into the editor. Add the following code on line 3:

    // create a new instance of the NetConnection object
myConnection_nc = new NetConnection();

    Tip

    If you do not see code hinting, the required library XML file was not installed properly. You must reinstall it.

    If Flash Communication Server is not running on your computer, you can use the installer to reinstall the authoring components.

    If Flash Communication Server is installed on your computer, you have to uninstall and reinstall the server, or run the installer on a computer that does not have Flash Communication Server installed and copy the following file.

    The file that Flash MX requires to populate the ActionScript panel is the communication.xml file. This file must be placed in the following folder:

    %Install Path%\Flash MX\First Run\ActionsPanel\CustomActions\

  3. Trace the status of the connection to monitor if the connection was successful or failed. Ultimately, you use this process to send a message to the user should the connection fail. The method onStatus is an event that is invoked to handle status messages sent from the server:

    // handle any status changes and responses from the server
 myConnection_nc.onStatus = function(info) {
      trace("LEVEL: " + info.level + "   CODE: "+info.code);
};

    This is called overwriting the onStatus function. This is done because the NetConnect.onStatus function wasn't programmed and doesn't do anything. When the server's status changes, the onStatus function runs to handle the response. It now traces any messages from the server to the output window when the movie is tested. By building some advanced handling, you can create a great way to inform the user that something has happened to the connection.

    The way it works is simple. The server returns its messages as an Information object, which is stored in a function variable. In our case that variable will be info. The object has two properties (CODE and LEVEL) that you can access and challenge. The Call.Failed code and the connect.Rejected code each return an additional property. Appendix C,"Information Objects (Server and Client) Quick Reference," contains a library of every Information object used by Flash Communication Server objects on the server and within Flash MX. As a helpful hint, a description of what you should do when you receive this error is available in Appendix C.

  4. Make the connection call to the server specifying the server name, port, application, instance, and username. The Connect method sends the first command to the server. The first parameter of this function is the location of the Communication Server:

    // Make the connection to the server
myConnection_nc.connect("rtmp:/mySecondApp/myInstance", "Kevin Towes");

    This script assumes you are running Flash Communication Server on your local computer. If your server is not on the localhost or on the same domain as your SWF file, add the reference to the server (//192.168.0.112) following the RTMP:/. You will also notice that you have to declare the name of the instance following mySecondApp. The SimpleConnect UI component you used earlier didn't require this parameter set in the RTMP string. Flash Communication Server automatically sets an instance called _definst_ if one isn't specified. In this scenario, you create your own instance called myInstance.

    Following the rtmp:/application/instance string, we are going to add a custom parameter to send a username. We handle this second parameter at the server by using it to log the user in to the application and accept the connection request.

  5. Connect the two UI components to the connection using their connect() methods. Each Communication UI component has set methods that control the component using ActionScript. For a full listing of UI component ActionScript commands, refer to Appendix D,"Flash UI Component Objects Quick Reference." Each component has a connect() method that assigns it to a particular connection. Add the following code to reference the peoplelist_mc and connectionLight_mc components to the myConnection_nc server connection:

    // Connect the UI Components to the new connection
peopleList_mc.connect(myConnection_nc);
connectionLight_mc.connect(myConnection_nc);

That's it for the Flash ActionScript! You will have to develop some server-side ActionScript within the main.asc file to register the username with the UI component, but this example will run so you can test it. Save the file in either the application folder or a folder accessible by your second testing computer. Test the movie by selecting Control, Test Movie, or Ctrl+Enter.

If you have done everything correctly, you will see the connection light turn green. If it doesn't turn green, here are a few things to check:

  • Is the Flash Communication Server running? Test using the Administration Console or the App Inspector.

  • Is the application folder mySecondApp created within the applications folder?

  • Does the folder have the main.asc file in it with the command load("components.asc"); as the only command?

  • Is the ScriptLibPath mapped properly to the scriptLib folder? You can check this by opening the file: \\[serverInstallPath]\conf\_defaultRoot_\_defaultVHost_\Application.xml. Note, when you change this, you will need to restart the virtual host, or the server.

When your light is green, you will notice that your username doesn't appear in the PeopleList component. Don't worry; it won't display until you add some server-side script to handle the connection. So let's write the required server-side script to finish the job. Unlike Flash ActionScript, server-side ActionScript is case-sensitive (x != X). Now, step through the process of creating the ActionScript:

  1. Open the main.asc file in your favourite JavaScript editor or Dreamweaver MX.

  2. Overwrite the onConnect event. Application.onConnect will always be invoked when a Flash player requests a connection. Overwrite the .onConnect() function to perform two tasks just as you did with the onStatus() function inside Flash MX. Add the following code below the Load command in the main.asc file to start the function definition:

    application.onConnect =function(newClient,newUserName)
{

    Two parameters are sent from the player: the server string (newClient) and your name (newUserName). You can pass as many parameters as you need to the application.onConnect() method. A simple example might be to also handle a password variable. The server string is used to access a unique variable scope for the instance of the application. Each instance uses its own variable scope, which is important to maintain security of the instance. The property username will be set to the value of the newUserName variable.

  3. Accept the connection. The method acceptConnection() informs the player requesting the connection that the connection can be established:

    //Accept the connection from the user.
application.acceptConnection(newClient);

    This command does two things. First, it instantiates the Client object on the server (more on the Client object in Chapter 11, "Server-Side ActionScript") and second, it invokes the onStatus handler on the Flash player sending the Information object code value NetConnection.connect.success. You can use this method to create server-side authentication. Using a simple IF statement or even database matching, you can allow or deny connection requests. There is also a method called rejectConnection() that does not allow the client to connect. The Reject command also invokes Flash's onStatus handler sending the code Netconnection.connect.rejected.

  4. Register the name with the UI component. This command sets the username within the framework used by the Communication UI components:

    //Set the global user name for the UI Components
gFrameworkFC.getClientGlobals(newClient).username =newUserName;

  5. Trace the username to the Live Logs window of the App Inspector and close the function definition. Tracing in server-side ActionScript is the same as tracing in Flash MX. The output of server-side traces are displayed in the application's instance view on the Communication App Inspector:

          trace("Hi There, " + newUserName);
}

  6. Save the main.asc file.

Reload your application using the Communication App Inspector in Flash MX. Reloading the application is required because you made a change to the main.asc file. In Flash MX, load the App Inspector by selecting Window, Communication App Inspector. Log in using the proper host and login/password combination. Select the active instance mySecondApp/myInstance entry and click View Detail. With the Live Log tab selected, click Reload App. If you don't see this active instance, test your Flash movie again.

When Reload App is clicked, notice how the Live Log acts as the server-side ActionScript trace window.

Test your application again in Flash MX using Ctrl+Enter. Keep your eye on the App Inspector. The trace that was placed within the Application.onConnect is output to the App Inspector when you load your application. You should see the words "Hello There, Kevin Towes". If you put a different name in the connect string, you will see that.

The first connection is always the hardest. If you have a problem with the application, or are receiving errors in the App Inspector, the first thing to check is case sensitivity. Confirm each variable name and function against the example's ActionScript listing below.

Listing 6.1 Full Server-Side ActionScript Listing
application.onConnect =function(newClient,newUserName){
      //Accept the connection from the user.
      application.acceptConnection(newClient);
      //Set the global user name for the UI Components
      gFrameworkFC.getClientGlobals(newClient).username =newUserName;
      trace("Hi There, " + newUserName);
}

Exercise 6.2: Allow Multiple Users to Connect

Now that you can connect to the server, why not invite your friends to see what cool things you can do? Let's add a login prompt (similar to the SimpleConnect) so other people can connect and identify themselves. To accomplish this, all that is required is to wrap the connection string in Flash MX with a function. The function and connect calls are invoked when a login button is clicked. The hard-coded name also is changed to reference the value of a text input field. Exercise 6.2 steps you through the process.

First, save the document as a new name so you can keep the original. Save the FLA file as Step2-MultiConnect.fla in the same folder. Next, add some items to the Flash stage. You need the following:

  • One text prompt to ask the user to enter his name.

  • One input text field with the instance name login_txt.

  • One PushButton UI component as a login button with the label "login."

Set the Click Handler of the PushButton to appLogin. This function will be scripted shortly to establish a connection with the user's name. Your interface should look like Figure 6.5. Notice the Properties panel with the PushButton values.

Figure 6.5. Lay out your stage similar to this example. The Properties window is displayed because the PushButton is selected.

Now, let's rearrange the code you just wrote so the connection isn't made until a user enters her name and presses the Login button. To achieve this, the Connect method is wrapped in a new function called appLogin. This function is called when a user clicks the Login button (you specified this in the Click Handler property for the Login button). The hard-coded reference to the username in the connect string is made dynamic by referencing what the user enters into the input box "login_txt". Now, step through the process of creating the ActionScript:

  1. Open the ActionScript panel (F9) containing the code for this movie in Flash MX. If you cannot see the code, make sure you have selected Frame 1, Layer 1 in the Timeline.

  2. Place your cursor above the line connecting myConnection_mc to the server. Create a blank line in the code and enter the following line of code:

    appLogin = function() {

    This is the start of the new appLogin function, but you have to close it now.

  3. Move your cursor to the end of the line containing the peopleList_mc.connect() string and press Enter to create a new line.

  4. Close the function with a closing curly bracket (}) in the line above the connectionLight_mc.connect string. The connectionLight.connect method is outside the function because it displays the current state of the connection, even before the connection has been established.

Your final code should look similar to what appears in Listing 6.2.

Listing 6.2 Final Flash ActionScript: Step2-MultiConnect.fla
// Include the Debug Class file
#include "NetDebug.as"

// create a new instance of the NetConnection object
myConnection_nc = new NetConnection();

// handle any status changes and responses from the server
myConnection_nc.onStatus = function(info) {
      trace("LEVEL: "+info.level+"  CODE: "+info.code);
};
// connect the application when the login button is pressed
appLogin = function () {
      // Make the connection to the server
      myConnection_nc.connect("rtmp://192.168.0.112/mySecondApp/myInstance", login_txt.
  text);
      // Connect the UI Components to the new connection peopleList_mc.connect(
  myConnection_nc);
};
connectionLight_mc.connect(myConnection_nc);

Save the Flash movie and test it (Ctrl+Enter). You will notice the ConnectionLight is red. This illustrates no connection. Enter your name in the box and press Login. The light turns green when it connects, and you see the name you entered in the PeopleList component when the server accepts the user.

Locate the SWF file that was created in the same folder as the FLA file. Double-click it or drag it into a web browser leaving the player running in Flash MX. Log in, and you now see two names in the PeopleList box (see Figure 6.6).

Figure 6.6. The application is running within a browser. You can see there are two people logged in.

Tip

Always make sure you create the onStatus function before you connect. This ensures that you will see any status changes (errors and such) from the server as they happen. The best practice is to create nc.onStatus immediately following nc = new Netconnection.


Summary

Connecting a Flash movie to the Flash Communication Server is not difficult. The NetConnection() object is the foundation for all communication between the server and the client. Consider it similar to connecting your computer to your Internet service provider. After the connection has been established and authenticated, you can send email, watch a video, download music, or play a video game online. You could build all of that in Flash MX, but that's another book. The NetConnection.connect() invokes the Application.onConnect() method on the server and is the best way to handle initial security for your connection. It sets up the appropriate instance to make sure your private data or conversations are kept private. Server-side handling might extend to authenticating against a database, or even an LDAP server.

In the next two chapters, you will learn how to communicate over this connection. Always remember to connect the Flash client objects and streams you want share.


Chapter 7. STEP 7: Streaming Video with NetStream()

The NetStream() object makes your Macromedia Flash player the most widely distributed streaming player in the world. This object allows you to receive live streaming video and audio from anywhere in the world. You can send synchronized messages within the stream to control elements or text (think closed captioning) within your Flash movies. If that wasn't enough, you can also send (or publish) live streaming video and audio from any device that supports Flash Player 6! It's like the best of an instant messenger and a great media player all rolled into one.

This chapter will introduce you to one of the most powerful live streaming video tools you have ever seen. Not only will you learn about the technology, but you will also review some basic concepts of video production and media streaming.


Overview

NetStream is powerful for four reasons:

  • Availability of the player

  • Authoring environment

  • Synchronized message broadcasts

  • Quality

The NetConnection() object, as you read in Chapter 6, "STEP 6: ActionScript with NetConnection()," is a two-way persistent connection between the Flash player and Macromedia Flash Communication Server MX. NetStream uses the NetConnection object to send or receive a stream with the server. Multiple streams can exist over a single NetConnection, but each stream can only travel one way.

As you saw in Chapter 4, "STEP 4: "Simple Chat and Video Conferencing," the AVPresence components allowed you to send and receive at the same time. In that example, two streams were established between the Flash player and the server—one to receive and one to send. You can also send messages over the NetStream. This is how someone could "capture" a AVPresence window, and it would appear on all computers. Messaging will be discussed in Chapters 9, "STEP 9: Controller and Subscriber Applications," and 12, "Client-Side (Flash) ActionScript."

The Flash Communication Server acts as a facilitator, like a hub that connects and synchronizes Flash players together. A persistent relationship with the server is always maintained with each player until the connection is closed or disconnected. There are two methods for communication over NetConnection: streamed media and distributed data objects (SharedObjects). SharedObjects will be discussed in Chapter 8, "STEP 8: Collaboration with SharedObject()."

Streamed data can exist in three forms:

  • Video

  • Sound

  • Text (messaging)

There is also an assumed fourth form: a video with sound attached. The Flash Communication Server introduces the NetStream() object to Flash to handle streaming media feeds originating from the Flash player or from the server. The NetStream() object communicates with the server using the NetConnection() object. It connects with the server-side Stream() object.


Streaming Video and Bandwidth

A popular feature of the Communication Server is its native ability to stream audio and video. Flash Player 6 supports video prepared using either Macromedia Flash MX's built-in Sorenson Spark audio/video compressor or the external, third-party tool, Sorenson Squeeze. The Squeeze product includes a "professional" upgrade to Sorenson Spark, called the Sorenson Spark Pro codec. Higher quality video and bandwidth optimization are just two key benefits. Using videos encoded with either technology, you can natively embed video or dynamically load video (SWF or FLV files) from a remote server using the Flash MX loadMovie() method with no Communication Server.

Note

Sorenson is the company that developed the compressor, or codec algorithm, for Macromedia. Sorenson made its name supplying the codec used by Apple QuickTime. A codec (short for code/decode) is required to encode a video from one format to another. Every player that can play a video format requires the decode codec. The only codec supported by the Flash player is Sorenson Spark. For more information on the codec visit http://www.Sorenson.com.

Note

For Flash to display video, it must be encoded using the Spark compressor. Files must be of type FLV or SWF. You cannot dynamically load AVI, QuickTime, or DV files without first compressing them. You can import these formats into Flash if you do not plan to load them dynamically.

So if you can load a movie dynamically with Flash, what does the communication server do differently? The process of streaming adds a lot of benefits. The most obvious is the ability to stream live video. Table 7.1 compares the features of dynamically loading a video using the loadMovie() object and using the Flash Communication Server's NetStream() object.

Table 7.1. Comparison chart between methods of loading server video dynamically.

Dynamic Video Using LoadMovie()

Dynamic Video Using NetStream()

Video is forced to match the frame rate of the calling Flash movie.

Video retains its encoded frame rate (fps).

RAM is allocated on the client to store the entire movie before loading begins. This can cause problems, particularly on Mac where memory is set as a finite amount per application.

RAM is allocated for only the length of the buffer for the stream. This is great for devices that don't have a lot of RAM; for example, mobile devices.

Flash has a 16,000 frame limit on any movie, which supports only a few minutes of video (22 minutes at 12fps).

Video can be sent from the server 24x7. There is no limit.

Seeking a video forward (fast-forward) before it has been loaded is not possible until it has completely loaded.

Recorded video can be seeked forward to any spot, whether it has loaded or not. You can also display a single "poster-frame" at any point in the movie.

If bandwidth becomes restricted before the video is loaded, the video will pause to continue loading.

Streamed video will drop frames to keep sync and ensure a seamless transmission if bandwidth becomes restricted.

Video quality cannot be switched in real time to increase or decrease bandwidth load. To change bandwidth, a separate loadMovie() command must be issued, and video will restart.

Video quality can be switched in real time to increase or decrease bandwidth load. This allows one stream to work in multiple bandwidth configurations so there is no need to encode a stream in multiple bandwidths for different clients.

This is not possible with loadMovie().

Video stream can be stopped while audio continues to save bandwidth (if required).

This is not possible with loadMovie().

Audio stream can be stopped while video continues to save bandwidth (if required).

Excited yet? Now Flash Player 6 is acting like one of the big three streaming media players: RealOne player, Windows Media Player, or QuickTime player.

A Quick History Lesson on Streaming

You may be familiar with the concept of "streaming" through such Internet devices as the Real Player (now called RealOne), Windows Media Player, or QuickTime. Streaming is the process of delivering synchronized pre-recorded or live video and audio to multiple computers in real time. In 1998, the hype on streaming media was in its highest state: Radio stations were streaming their signal, Internet TV shows started, and there was even a case in Toronto, Canada where a company (iCraveTV) streamed every television station transmitting over the public airways. This whole fetish began in 1994 with the famous Internet transmission of the Rolling Stones Voodoo Lounge concert to 1,000 computers around the world. The technology of the day was called MBONE (multi-casting backbone), and it wasn't pretty.

Today, Internet streaming still hasn't completely sorted itself out, and expectations are that there are at least another 10 years or so before it will. But that is just this author's opinion. Video conferencing, another form of streaming media, was heralded as the next killer app. The product, CU-SeeMe, was the leader in providing video conferencing software for desktop computers. An interesting connection between the Rolling Stone's MBONE concert and CU-SeeMe, is that the San Francisco company who organized the Stone's concert, Internet Access played a part in the rollout of the CU-SeeMe company. Back in the day, CU-SeeMe created a communication server called Reflector that allowed 20 or so people to connect to "see" each other. There was actually an initiative in place to "schedule" Reflector times.

In 1995 Progressive Networks (known today as Real Networks) created the Real Player. This revolutionary technology was built to communicate using a new protocol. Like Macromedia, Progressive Networks realized it needed its own protocol specially designed to handle media. HTTP, after all, was not intended for sustained connections, a requirement for delivering time-based media like video. The rtsp:// (Real Time Streaming Protocol) was created by Progressive Networks to send live or recorded video and audio over the Internet. In 1995, the population of people on the Internet was small, and those that were online connected at average speeds of 14Kbps and 28Kbps. Compare that to today, where home users connect at an average speed of 1,024Kbps (1Mbps) or higher. Microsoft soon followed, introducing their streaming server solution with a major enhancement to its Windows Media Player as the preferred client. Before the third player, QuickTime, began its streaming career, a new XML authoring format called SMIL (Synchronized Multimedia Interface Language) was created. This language was based on XML and was used to handle multiple streams of synchronized data. This technology was adopted quickly and content producers, such as CNN, quickly built applications to stream video, audio, dynamic text, and image content, such as news and weather.

Apple QuickTime seemed to be the last in the streaming server market, but it had already established a standard of high-quality video in partnership with Sorenson Media. Sorenson recently worked with Macromedia to create a new media encoder algorithm to compress video into files that can be read by Flash Player 6. Overnight, with the release of Macromedia Flash MX, Sorenson increased its user base by incredible numbers.

So, how does this get back to the developer? One major element that eats at the Internet developer is surrendering to one of "The Big Three" to deliver video over the Internet. Macromedia has changed everything with the Flash Communication Server. The Big Three have fought for market share for years. They each support Flash movies, but always saw the Flash player as a an enhancement, not a competitor. Here is an interesting statistic: The Flash player is the single most adopted software in the history of the world by both the business and consumer market. Its market share is bigger than The Big Three media players combined; it's bigger than the Microsoft Windows operating system! Macromedia's framework for the developer to produce streaming media within the Flash player has changed the rules, once again over night.

Ok, that's enough history. To get the best understanding, let's start streaming!

Playing a Prerecorded Video

Our first Flash Communication Server exercise in video is streaming a prerecorded video from the server to the Flash player. Flash MX supports most major video file formats including the following:

  • Windows (AVI, WMV, ASF)

  • Digital Video (DV)

  • MPEG (MPG, MPEG)

  • Apple QuickTime (MOV)

To use video, Flash must first convert the video into a format it can use and control. You have two options for file formats in Flash: a Flash movie (SWF) or a Flash video (FLV) file. When you stream video, you must use the FLV format. The SWF and FLV formats are encoded using the Sorenson Flash video codec, Sorenson Spark.

Video compression techniques alone can fill a book. If you plan to incorporate professional video with any Flash application, consider investing in one of these books. This book will introduce you to both technologies and provide some recommended compression settings in both Flash MX and Sorenson Squeeze, but the focus is on the streaming of video.

Exercise 7.1: Flash Video Compression Using Flash MX

In this exercise you will convert an existing QuickTime video into a Flash video file using the built-in Sorenson Spark compressor in Flash MX. If you do not have a video to work with, you can download a video from the book's web site.

The Sorenson video encoder (see Figure 7.1) built into Flash MX is easy to use. The file that will ultimately stream is not loaded into your movie within Flash MX. It will be called into your movie using NetStream() at a later stage. Follow these steps to convert your movie into a Flash video file using Flash MX.

Figure 7.1. Sorenson Spark is the built-in video compressor for Flash MX.

  1. Create a new document with Flash MX. You will not be saving this document, just using it to compress the Flash movie.

  2. Import the video into Flash MX the same way as importing any asset. Click File, Import to Library, and then browse and select the video to convert.

  3. Click OK. Flash MX will give you two import options (see Figure 7.2). Select the Embed Video option, and then click OK.

    Figure 7.2. Flash MX will give you two options when you import a video to the library. To build FLV files, select the Embed Video option.

  4. The Import Video Settings window (see Figure 7.3) displays conversion settings you can control for this movie. This is your only time to edit these settings. Experiment with the following settings to get a feel for how they affect the video:

    • Quality. Allows you to select a range between 0 and 100. Setting Quality to 0 results in maximum compression, 100 is least compression and lossless quality. Recommended settings are between 60 and 80.

    • Keyframe Interval. Creates video keyframes when there is a large change in the pixel color (resulting in movement) between frames. Setting Keyframe Interval to 0 turns off keyframes, a value of 30 keyframes every frame. If you set the keyframe rate too high, your file size will increase dramatically. Setting the rate too low results in a very poor quality video. If you have a lot of motion (as in a movie trailer), use more keyframes. If there is not a lot of motion (as in a talking head shot), lower your keyframe interval.

    • Scale. Changes the size of the video frame in proportional values of width and height.

    • Synchronize Video. Conforms the video to the current frame rate of your Flash MX movie. To retain the original frame rate (recommended), turn off Synchronize Video. Doing so, however, might produce a choppy playback. If your video frame rate (fps) is too high, some computers may not have the processing speed to playback smoothly.

    • Frames Ratio. Plays one frame of video per one Flash frame. It's recommended to leave this ratio at 1:1.

    • Import Audio. Includes the audio channel in the encoding process.

      There is no way to describe which setting is best. Each unique video will compress differently. Some factors to consider are the amount of motion in your video, the speed, the sound, and the way it was captured. For example, if you digitize a video from a digital camera, you will get much different results than if you digitize from a VHS tape because of the quality difference of the recorded matter. If you have a video feed in low light, you will get different results than with ample light.

      Clearly the best quality will result in setting all settings to 100%, but this will potentially result in a large file with a lot of unneeded elements, not to mention you risk consuming unneeded resources on the client's computer. You should experiment by importing a video and max out the settings, and then import it again with the minimum settings.

      Figure 7.3. The Sorenson Spark built-in compression options.

  5. Click OK when you are finished setting the compressor. Flash MX will then compress the file and place it within the Library.

  6. Open your Library by pressing F11 (or choose Window, Library), as shown in Figure 7.4. You will see the new video (still named by its original source name).

    Figure 7.4. The Library panel menu gives you access to the Properties option for the selected library item.

  7. Select the video, and open the Library panel properties (you can also Right-click (Cmd-click for the Mac) to open this menu. Click Properties.

  8. Export the movie to a Flash video file by clicking the Export button in the Properties window (see Figure 7.5).

    Figure 7.5. The properties of the embedded video gives you the option to export the clip as a FLV file.

  9. Save the video to your hard drive. This file will ultimately be placed in your Flash Communication Server application folder. Don't do it yet.

That is all you need to do to convert your digital video in Flash MX to a format that can be streamed by the Flash Communication Server. Exercise 7.2 will introduce you to the difference between compressing using Flash MX and using the Sorenson Spark Pro Compressor within Sorensen Squeeze.

Exercise 7.2: Video Compression Using Sorenson Squeeze

If quality is what you need, consider investing in Sorenson Squeeze, which contains the upgraded Sorenson Spark Pro compressor—the big brother of the compressor used in Flash MX (see Figure 7.6). For about $200, Squeeze has many features that can increase the quality and delivery of your video. Squeeze is a great product with a lot of features, including batch processing to save you time compressing large files. The following exercise will introduce you to some of these features.

Figure 7.6. Sorenson Squeeze contains the upgrade to the internal video.

Using the same QuickTime video used in Exercise 7.1, this exercise will step through the process of converting video into Flash video destined for streaming with the Flash Communication Server. You can download some sample video clips from this book's web site.

  1. Open Sorenson Squeeze.

  2. Open a video file using the folder icon or simply drag the video onto Squeeze. The video will be displayed in the player window (see Figure 7.7).

    Figure 7.7. The Sorenson Squeeze encoder.

  3. Click the Flash Video icon in the toolbar above the video (see Figure 7.7).

  4. Open the Compression setting for Broadband by clicking Edit, Compression Settings, Broadband (see Figure 7.8).

    Figure 7.8. Edit the Compression settings by selecting the option in the Edit menu.

  5. In the Compression Settings window (see Figure 7.9), make sure the Flash FLV tab is selected. This window is the compression settings for Broadband video. Squeeze allows you to simultaneously compress different versions of your video for high bandwidth and low bandwidth connections.

    Figure 7.9. The Compression settings within Squeeze add much more control than Flash MX.

    As you can see, Squeeze already offers you much more control over your video compression than Flash MX did. Let's take a quick look at the settings:

    • Video Compressor. You only have one choice here for Flash Video: Sorenson Spark.

    • Audio Compressor. Two options are available to you: Fraunhofer MP3 or RAW audio. Each compressor has different qualities depending on the type of audio you have (talking versus music, for example). It is recommended to use MP3 encoding with a lower bit rate.

    • Video/Audio Data Rate. The value here is related to the amount of bandwidth your client has. For example, a modem can support a bit rate of 56 kilobits per second (Kbps). The estimated bandwidth is video data rate plus audio data rate, so a 56K modem will not support video and audio with video encoded at 56Kbps. Other than MP3 audio, all audio data rates are set using the independent vendor options window. Please read the section on Bandwidth later in this chapter.

    • Video Frame Rate. This is also known as frames per second or fps. Normal NTSC video from a video camera has a frame rate of 30fps (well, actually 29.97, if you are a perfectionist). Images shot using a film camera are recorded at 24fps. Usually video displayed over the Internet uses 15fps. This means you will see 15 images per second (about half of the original source). At 15fps you will not visually notice much of a difference in the video. Once you dip below 15fps, you will start to notice your video is jumpy. The higher the frame rate, the smoother your video. It is recommended using the ratio options (1:2) for this setting to gain maximum quality.

    • Video Method. You have two choices: constant rate or variable rate (2-Pass VBR). For the highest quality, select the variable rate. For fastest compression time, select constant rate. For any production, you should use the 2-Pass VBR option.

    • Video Frame Size. This is the actual frame size of your video. It is recommended selecting a 4:3 ratio for North American Video (NSTC); however, you can select the width and height independently. Recommended settings are either 320x240 or 160x120.

    • Audio Sample Rate. This is the audio equivalent to dots per inch when scanning a photograph. It represents the samples per second the compressor will use to compress the audio track. CD quality is 44,100kHz, but you can usually get away with 22,050kHz.

    • Channels. The two choices are Stereo and Mono. Stereo immediately doubles the size of your audio. A talking head or a single voice track should be Mono. Music, if stereo is important, should be set to Stereo.

    • Sorenson Spark Pro Options. The professional version of Spark gives you even more control over your video compression, handling drop frames, keyframes, and allowing a minimum quality threshold (see Figure 7.10).

      Figure 7.10. The Options button displays the expanded Sorenson Spark encoder options. Change these settings using the Encode/Playback tab.

  6. Click OK to return and exit the Compression Settings window.

  7. Apply filters to your video by clicking Edit, Filter Settings (Ctrl+F). Filters allow you to affect the movie before it gets converted. You can adjust the standard Brightness, Contrast, Gamma, and Black and White Restore levels (Figure 7.11). You can also de-interlace and crop your video, add fades to the ends of your video, and clean the audio track with a normalization process.

    Figure 7.11. The Options button displays the expanded Sorenson Spark encoder options. Change these settings using the Encode/Playback tab.

    Figure 7.12. Click the Bandwidth bars to select the compression settings for output. You can select multiple settings to encode at the same time.

    Tip

    Cropping your video by two pixels on all four sides will help remove unwanted video noise on the edges during capture. This trick usually helps keep the file size down. Also, turn on Auto Remove Interlacing and Normalize Audio.

  8. Assign the compression settings you want to encode. Select Compression, Broadband. This will place the job in the Output Files window.

    The Output Files window displays compression jobs queued to be "squeezed." It will detail the highlights of your compression settings.

  9. Add a low-bandwidth version of your video to the queue by clicking Compression, Modem. A second job will be placed in the queue.

  10. Select the Output Folder by clicking Edit, Output Folder. This folder will contain the finished FLV file.

    Tip

    Using an output folder on the same hard drive as the source file will speed up the encoding process. Outputting the file over a network share should be avoided. If the network is disconnected during the compression, your file will be corrupt and the encoder will fail.

  11. Click the Squeeze It button below the Output Files window to begin the encoding process. A Progress window will be displayed; it will take two passes on the video (see Figure 7.13). The first pass is almost equivalent to the Flash MX output. During the second pass, you will notice a significant improvement in the preview.

    Figure 7.13. Squeeze will display the status and the current file it is working on.

Squeeze compresses all files queued in the Output window, and displays a report when complete. At the end of the process, you will be left with two files—one with the suffix _broadband and one with the suffix _modem. These naming conventions will be useful when the files reach the Flash Communication Server.

Sorenson Squeeze also includes a Folder Watching utility. This handy tool monitors a folder of your choice for any new video files. Simply by placing a file within this folder with Squeeze running, you trigger Squeeze to compress it. We won't get into that specific feature, but you should investigate it.

With your Flash video files ready, you are now prepared to stream them using the Flash Communication Server.


The NetStream() Object, Methods, Properties, and Event

The NetStream() object is used to connect multiple one-way streams between the Flash player and the Flash Communication Server using the NetConnection method. Consider this object as a channel inside the NetConnection. Each channel can be either sending (publishing) or receiving (subscribing to) data. You can connect as many "channels" to your server connection as your bandwidth permits. Consider the relationship of the telephone and your phone company for a moment.

You cannot connect two telephones together and expect them to work without the phone company. You need a connection and a telephone service provider. Your local telephone company redirects your connection to other telephones within their network, or it establishes a series of connections with other telephone service providers to connect a telephone in their network. The microphone in your telephone is a stream that can only send (or publish) an audio stream through the phone company to the receiving (or subscribed) phone at the other end. The earphone subscribes to a one-way stream from the phone company to allow you to listen to the sender on the other end.

Traditionally, communication over the Internet was like talking into a walkie-talkie where only one person could speak at a time. If you were not speaking, you were listening. This technique is called half-duplex. A half-duplex system shares a single stream over a connection for both sending and receiving. Communication using this technique is like raising your hand in class to ask a question. It is not a natural way for humans to communicate. The Flash Communication Server is a full-duplex system. This simply means that each person connected using this technology can talk, just like they do over the telephone.

Deploying this example using the Flash Communication Server would require two streams per Flash player—one to publish the microphone to the server, and one to receive the stream being published by another Flash player. The server would handle four streams in total with this scenario. If you have three people connected, each Flash player would handle three streams, and the server would handle six streams. Let's say that person in the three-way call has a video camera attached to their Flash player. Now each Flash player will publish two streams (one video and one audio), and receive four streams (two video and two audio) over a single connection. Getting the picture?

Just remember that a single connection can handle multiple one-way streams and you will be okay. In the next example, you will not publish streams, but set up the Flash player to play a prerecorded video from the server through one stream. More detail on publishing, subscribing, and bandwidth will be presented following the exercise.

NetStream() methods are:

  • .close() Removes a stream from the connection.

  • .setBufferTime() Determines the amount of memory used (in seconds) to preload video or audio before playing. This method is used when receiving (subscribing to) a stream from the server.

  • .pause() Temporarily pauses the playback of a stream.

  • .play() Resumes or starts playback over a stream.

  • .receiveAudio() Begins streaming audio to the capacity of the buffer, but does not play.

  • .receiveVideo() Begins streaming video to the capacity of the buffer, but does not play.

  • .seek() Fast forwards or rewinds the stream. When seeking a stream, the position is relative to the current position. So seeking 10 seconds would be 10 seconds from the time property.

  • .attachAudio() Connects a microphone to the stream when publishing to the server.

  • .attachVideo() Connects a camera to the stream when publishing to the server.

  • .publish() Begins publishing a stream. This method determines if the stream is recorded, live, or append, which will add on to an existing movie. Recorded video is stored as a FLV file within the Application/streams/instanceName folder on the server.

  • .send() Calls a server function using the stream when publishing.

The .setBufferTime(), .pause(), .play(), .receiveAudio(), .receiveVideo(), and .seek() methods are used with a stream subscription. The .attachAudio(), .attachVideo(), .publish(), and .send() methods are used with a stream publication.

The NetStream properties are:

  • .bufferLength A read-only property; contains the length of time the NetStream currently has in its buffer. The output is in seconds.

  • .bufferTime Declares how much buffer time is available to the NetStream.

  • .currentFPS A read-only property; reports the current frames per second being sent or received over a NetStream. It is read only, so you can't change it.

  • .time A read-only property; displays the current number of seconds the stream has been either playing or publishing. A value of 0 is set when play starts or the .close() method is called. This property is valuable for building the seek function.

The only NetStream event is OnStatus. This event will be called to handle NetStream status changes. Status changes include errors, connects, and disconnects.

Exercise 7.3: Streaming Video from the server

This exercise will open a NetConnection() to the server. Using the NetStream() object, you will stream the video you just encoded. There are two components (as always) to this exercise: the server and the Flash application. Set up the server first:

  1. Create a new application folder in the flashCom/Applications folder on your server. Call it myVideoApp.

  2. Create a folder called streams within the myVideoApp folder.

  3. Create a folder called myInstance within the streams folder. This folder will be the name of the application instance used in the connect string.

  4. Move any Flash video files you want to stream into this folder. These files must have been compressed using the Sorenson Spark or Spark Professional codec. They must be Flash video (FLV) formats.

  5. Copy the files main.asc and Step2-MultiConnect.fla used in Chapter 6.

    The source files for Chapter 6 are available for download from the book's web site, if you didn't do the exercise in Chapter 6.

  6. Rename the MySecondApp.fla file to VideoStream.fla. Your server folder tree should now look similar to what appears in Figure 7.14.

    Figure 7.14. Your videoApp folder structure and files should look like this.

    When you are working with streaming video, you must define the instance as a folder within the application/streams folder and place all FLV files that are required by the application within that folder. This makes things a little trickier to manage, but it is a great security feature to ensure users access only what they should. With this in place, let's move on to building the Flash interface. In this example, we are building on the application you built in Chapter 6. The VideoStream.fla file should already have ActionScript to connect to the server and a login prompt for the user.

  7. Open VideoStream.fla in Flash MX.

  8. Open the Library panel (F11).

  9. Add an embedded Video object. Click the Properties panel on the Library panel to reveal a menu. Select New Video from the list (see Figure 7.15).

    Figure 7.15. Use the Library panel menu to create a new embedded Video object.

    A new embedded Video object will be created in the Library.

  10. Drag the new video on to the Flash stage.

  11. Name the instance of the embedded Video object my_video in the Properties panel. Remember to have the Video object selected on the Flash stage to access the Properties panel. Using the suffix _video in the name will trigger the video code hints in the ActionScript Editor.

  12. Open the ActionScript panel (F9).

  13. Confirm the script in the panel matches Listing 7.1:

    Listing 7.1 ActionScript for videoStream.fla
    // Include the Debug Class file #include "NetDebug.as"
// create a new instance of the NetConnection object
myConnection_nc = new NetConnection();
// handle any status changes and responses from the server myConnection_nc.onStatus =
  function(info) {
      trace("LEVEL: "+info.level+"  CODE: "+info.code);
};
// connect the application when the login button is pressed
appLogin = function () {
      // Make the connection to the server
      myConnection_nc.connect("rtmp:/mySecondApp/myInstance", login_txt.text);
      // Connect the UI Components to the new connection
      peopleList_mc.connect(myConnection_nc);
};
connectionLight_mc.connect(myConnection_nc);

  14. Change the connection string to reference the new application, myVideoApp. The line should now read:

    myConnection_nc.connect("rtmp:/myVideoApp/myInstance", login_txt.text);

  15. If you like, test the movie to ensure everything is working. When you are satisfied everything still works, go back to the ActionScript panel. Immediately below the connect line, within the appLogin function, the streaming connection will be made and attached to the Video object on the stage. You will be amazed that this will only take three lines of code!

  16. Add a few line breaks below the myConnection_nc.connect string. All this code will be placed within the appLogin() function.

  17. Instantiate the NetStream() object to a variable called videoIN_ns. In this command you also connect the stream to the connection, myConnection_nc. This will become the source for your video.

    videoIN_ns= new NetStream(myConnection_nc);

  18. Add the onStatus event handler for NetStream:

    videoIN_ns.onStatus = function(info){
   trace("NETSTREAM LEVEL: "+ info.level + " CODE: "+ info.code);
}

    This handler will be called whenever the status of the NetStream changes. For a complete listing of every NetStream Information Object, refer to Appendix C,"Information Objects (Server and Client) Quick Reference." This appendix contains a listing of every Information object used with communication applications.

  19. Attach the new video source, videoIN_ns, to the embedded Video object on the stage:

    my_video.attachVideo(videoIN_ns);

    This is just like patching your TV with a video signal coming from your DVD. The attachVideo method defines where the video source is coming from.

  20. Start playing the video stream from the server:

    videoIN_ns.play("Sparky");

    This command tells the server which recorded file to stream. The server will expect to find the file Sparky.flv in the folder myVideoApp/streams/myInstance. The extension is assumed as .flv. There will be a default two-second buffer before the stream begins. The buffer can be changed using the .SetBufferTime() NetStream method. Buffering is important to ensure a smooth stream is accomplished. Too much buffer will consume too much RAM, too little will make the stream stall or re-buffer.

  21. Save your movie.

  22. Test the movie using Control, Test Movie or pressing Ctrl+Enter.

  23. Use Listing 7.2 to compare your ActionScript.

    Listing 7.2 The complete ActionScript code to connect a stream
    // Include the Debug Class file
#include "NetDebug.as"
// create a new instance of the NetConnection object
myConnection_nc = new NetConnection();
// handle any status changes and responses from the server
myConnection_nc.onStatus = function(info) {
      trace("LEVEL: "+info.level+"  CODE: "+info.code);
};
// connect the application when the login button is pressed
appLogin = function () {
      // Make the connection to the server
      myConnection_nc.connect("rtmp:/myVideoApp/myInstance", login_txt.text);
      videoIN_ns = new NetStream(myConnection_nc);
      // Status Change Handler
      videoIN_ns.onStatus = function(info){
         trace("NETSTREAM LEVEL: "+ info.level + " CODE: "+ info.code);
       }
      // Attach the video stream to the embedded video object
      my_video.attachVideo(videoIN_ns);
      videoIN_ns.play("Sparky");
      // Connect the UI Components to the new connection
      peopleList_mc.connect(myConnection_nc);
};
connectionLight_mc.connect(myConnection_nc);

When you log into your application, the ConnectionLight will turn green and the name you entered into the login will appear in the PeopleList, just like before. As soon as the connect is accepted, the videoIN_ns will connect a stream to the connection, and the server will start sending the Sparky.flv file to the player. You will see and hear the video playing on the Flash Stage just like Figure 7.16.

Figure 7.16. Your video should play within the Flash movie as soon as you log in.

You can add some simple video controls that will pause and play the stream or close it all together. You could also add a seek bar that would allow you to fast forward or rewind the stream quickly.

NetStream Roles

The NetStream you just used is called a subscriber stream. This is a stream that is in Receiver mode. The data with NetStream can flow only one way between the Flash client and server. As mentioned earlier, more than one stream per connection is possible. Exercise 7.2 used a NetStream subscription, meaning that the player was the receiver. With this situation, there is no publisher because the stream is prerecorded and stored on the server. There are basically two types of streams:

  • Publisher stream. The publisher stream is a sender stream. When your player publishes your camera or microphone, it sends the data to the server for distribution. The server makes the incoming stream available for subscription and connects the subscribed clients. The publisher stream can also send messages and text data to the server by calling server-side ActionScript functions. A good example might be the publisher presenting a slide show with a live video feed. The data stream could be used to advance a slide on all subscribed clients.

  • Subscriber stream. The subscriber stream is the receiver stream. A Flash player will use a subscriber stream to monitor video and audio distributed by the server. Text data can be sent to the subscriber from the server by calling a client-side function in the Flash application. The server needs to be invoked by an event or a publisher to send data this way.

Note

The only way multiple Flash players can connect without the Flash Communication Server is by running on the same computer using the localConnection() object. Flash clients on separate computers never connect directly, without passing through the Flash Communication Server.

The connection speed between the server and client is called bandwidth. Bandwidth is measured in bits per second. The easiest way to understand bandwidth is thinking about the connection your home computer has with its Internet provider. If you dial up using a traditional 56K modem, you are probably connecting at a bit rate of up to 56,000 bits per second, better known as 56Kbps. Cable modem or DSL connections can range from 256Kbps up to 10,000Kbps, or 10Mbps (megabits per second). Office computers are usually connected to servers through a LAN. Internal networks (LANs) usually have bandwidth between them of 10Mbps up to 100Mbps or higher.

How does all this relate to streaming? There is a direct relationship between bandwidth and the quality of the stream you can send or receive. The more bandwidth you have, the faster you will receive data. Faster connections mean you can send or receive larger files faster. File size has a relationship to the quality of video and audio. The larger the file is, the higher the quality. Smaller bandwidths cannot receive large video files fast enough to play them and must access smaller files, sacrificing quality. When a connection becomes slower due to network traffic, it is called latency. You can see this measured in the ConnectionLight UI component by clicking on it.


Playing Live Video

Now that you can receive video from the server, it's time to publish your camera and microphone to the server.

Connecting your computer's camera in Flash MX is very easy. One line of code will do it (provided you have a Video object on the stage called my_Video):

my_Video.attachVideo(Camera.get());

You can do the same with your microphone:

this.attachAudio(Microphone.get());

While a very neat trick, it really won't get you very far in communication unless you are a video artist building a montage of live Video objects. If you are that person remember, this is Flash; the Video object is just another object on the stage. Try wrapping it in a graphic and doing some animation with the Live Video window or playing with some interesting masks. Better yet, try connecting multiple cameras and Video windows.

Exercise 7.4: Publishing a Live Stream Using the Camera and Microphone Objects

The real magic happens when you can let other computers see your camera, and you can see theirs. Exercise 7.4 walks you through the process of publishing your camera and microphone to the server, building on what you have just created. You will use the publish method to record your camera's activity on the server. Exercise 7.5 will take this one step further and allow you to playback the live and recorded stream.

  1. Open the previous example, VideoStream.fla, in Flash MX.

  2. Save the Flash file as PublishCam.fla in the same folder, myVideoApp.

  3. Close or move the ActionScript window so you can see the Flash stage.

  4. Open the Library (F11).

  5. Drag a second instance of the embedded Video object to the Flash stage, and name the second embedded video instance play_video in the Properties window. This will be used to play the live and recorded video from the server.

  6. Rename the first embedded video instance, cam_video. This window will be used to display our local camera feed.

  7. Select the Flash UI components from the Components panel, and add two PushButton UI components to the Flash stage—one under each Video window. These buttons will be used to control the publishing and subscription feeds.

  8. Set the properties of the left PushButton to the following:

    Instance name: record_pb

    Label: Record Camera

    Click Handler: startPublish

    The Click Handler is now set to call a function that you will build shortly. This function will open a NetStream and start sending the camera feed to it.

  9. Set the properties of the right PushButton to the following:

    Instance name: play_pb

    Label: Play Video

    Click Handler: startPlay

    The instance name, play_pb, will be used to dynamically control the label of the button and the Click Handler. When the user clicks Play, it will change to Stop, and the Click Handler will change to stopPlay. You will add ActionScript for this shortly.

  10. Add two static text labels above each Video window. Enter Publish above the left window and Subscribe above the right.

  11. Save the Flash file.Your Flash stage should look like Figure 7.17. Notice the Properties window displaying the values for the record camera PushButton. You are now ready to build the ActionScript.

    Figure 7.17. Set up your Flash stage like this example.

  12. Open the ActionScript window (F9), and confirm your ActionScript against Listing 7.2. Like before, this ActionScript will build on what you have done previously but will become more complex.

  13. Remove the following videoIN_ns lines of code:

          videoIN_ns = new NetStream(myConnection_nc);
videoIN_ns.onStatus = function(info){
   trace("NETSTREAM LEVEL: "+ info.level + " CODE: "+ info.code);
}
      my_video.attachVideo(videoIN_ns);
      videoIN_ns.play("Sparky");

    This exercise will not be receiving video, and this script is no longer required.

  14. Attach the local camera feed, within the appLogin function, to the cam_video object on the Flash stage. In the place of the videoIN_ns code you just deleted, add this code after the .connect method:

    // attach the Camera feed to the video monitor; cam_video
cam_video.attachVideo(Camera.get());

    The Camera.get() function enables any camera attached to the computer. When this method is called, the user receives the Flash player's privacy popup letting him know that you are accessing his camera. Attaching the live camera to the Video object serves as the local video monitor for the user to see what will be captured. It also helps the user to position the camera.

  15. Create the startPublish() function after the appLogin function, at the bottom of all the ActionScript:

    startPublish = function() {
// Code will go here
}

    This function contains the ActionScript to open a new NetStream and publish the camera feed to that stream.

  16. Create the stopPublish() function at the bottom of all ActionScript:

    startPublish = function() {
// Code will go here
}

    This function closes the NetStream, which will stop publishing the camera feed.

  17. Add a couple empty lines within the startPublish = function(). Make sure you don't delete the closing bracket.

  18. Open a stream to publish the video within the startPublish() function. Where you added the empty lines place:

    publish_ns = new NetStream(myConnection_nc);

    This assigns a new NetStream to the variable, publish_ns, and attaches that stream to the NetConnection, myConnection_nc.

  19. Setup the publish_ns stream as a publish stream. Immediately following the line above, add the following code:

    // this will create a new FLV file in the myVideoApp/streams/myInstance Folder
// and set it to start recording
publish_ns.publish(login_txt.text, "record");

    The publish() method here is set to start recording any source to a dynamic filename. The filename on the server will be the name of the user currently logged in. If you type user in the Login field, then the filename would be user.flv. This file will automatically be inside the instance folder within the myVideoApp/streams folder. This method automatically creates the streams/[instance name] folder if it doesn't already exist.

  20. Attach the camera feed to the publish stream:

    // attach the video Source to the stream
publish_ns.attachVideo(Camera.get());

    You are still working within the startPublish() function. Yes, you can "split" the camera feed to many places. In this case, you will be sending the camera feed through the NetStream, but also to the embedded video on the Flash stage.

  21. Attach the microphone feed to the publish stream:

    // attach the audio Source to the same stream
publish_ns.attachAudio(Microphone.get());

    Attaching the microphone and the camera to the same stream combines both in sync to the same FLV file on the server.

  22. Change the label and the Click Handler for the Record button:

    // change the pushButton to a stop button,  change the label property, and the Click
  Handler property
record_pb.setLabel("Stop Recording");
record_pb.setClickHandler("stopPublish");

    This is the last step inside the startPublish() function. It changes the name displayed on the record button to Stop Recording. It also changes the function that will be called when it is clicked. If you are wondering what the setLabel and setClickHandler methods are, they are unique methods for the PushButton UI component. What they do is change the name on the button (label) and change the function the button will call (ClickHandler) dynamically.

    That's it for the startPublish() function. Make sure you didn't delete the closing bracket. Click the Check Syntax check mark at the top of your ActionScript Editor to make sure your code does not contain errors. Review the full code in Listing 7.3 to compare your code. You will now work inside the stopPublish() function.

  23. Call the Netstream Close() method, stopping the stream publication. Add the following line inside the stopPublish() function:

    // close the netStream, to stop the record
publish_ns.close();

  24. Change the label and the Click Handler of the Record button back to its original state:

    // change the button label, and the click handler
record_pb.setLabel("Start Recording");
record_pb.setClickHandler("startPublish");

  25. Save your Flash movie; you are done!

That's it for the stopPublish() function and this part of the coding exercise. You are now ready to test your movie. Review the code in Listing 7.3 to ensure you have everything in the right place. There are some extra comments in this code to help you out. Comments start with a double slash, //.

Listing 7.3 Final ActionScript listing for PublishCam.fla
// Include the Debug Class file
#include "NetDebug.as"
// create a new instance of the NetConnection object
myConnection_nc = new NetConnection();
// handle any status changes and responses from the server
myConnection_nc.onStatus = function(info) {
      trace("LEVEL: "+info.level+"  CODE: "+info.code);
};

//
// connect the application when the login button is pressed
//
appLogin = function () {
      // Make the connection to the server
      myConnection_nc.connect("rtmp:/myVideoApp/myInstance", login_txt.text);
      // attach the Camera feed to the video monitor; cam_video
      cam_video.attachVideo(Camera.get());
      // Connect the peopleList UI Component to the new connection
      peopleList_mc.connect(myConnection_nc);

};
// Connect the connection Light UI Component to the new connection
connectionLight_mc.connect(myConnection_nc);

// ————————
// PUBLISH METHODS
// ————————
startPublish = function () {
      publish_ns = new NetStream(myConnection_nc);
      // this will create a new FLV file in the myVideoApp/streams/myInstance Folder
      // and set it to start recording
      publish_ns.publish(login_txt.text, "record");
      // attach the video Source to the stream
      publish_ns.attachVideo(Camera.get());
      // attach the audio Source to the same stream
      publish_ns.attachAudio(Microphone.get());
      // change the pushButton to a stop button,  change the label property, and the
  Click Handler property
      record_pb.setLabel("Stop Recording");
      record_pb.setClickHandler("stopPublish");
};
stopPublish = function () {
      // change the button label, and the click handler
      record_pb.setLabel("Start Recording");
      record_pb.setClickHandler("startPublish");
      // close the netStream, to stop the record
      publish_ns.close();
};

When you have logged in and started to publish your camera feed, your application should look like the example in Figure 7.18.

Figure 7.18. The completed exercise showing the live camera window.

While you are recoding yourself, take a look at the Communication App Inspector inside Flash MX (click Window, Communication App Inspector to open it), as shown in Figure 7.19. When you have logged in, select the application instance, myVideoApp/myInstance. You will not see anything in the live logs yet. Switch over to your running application and log in and start publishing again. Your Live Log should display the following trace output from the server.

Figure 7.19. The App Inspector window displays the server trace information when streams are created and published.

Figure 7.19 is displaying activity when a new user logged into the application. Notice how the server deleted the NetStream that was previously being published, and then immediately re-created it. It is also tracing when the publish command was received and when recording started.

In Figure 7.19, you can see a NetStream was deleted and the server did "garbage collection" when a new connection from you was established (when you logged in again). When you click the Record button, you see a new NetStream is created and gives the ID 1. The server traces the name of the new stream and traces when recording starts.

Exercise 7.5: Playing a Live Stream

Now that you are able to publish a stream to the server, your next step is to play it on another computer. Because we set the publish method to record, you will not only be able to connect to the live stream, but when the stream stops publishing, you will see the recorded version immediately.

This exercise will continue where you left off in Exercise 7.4. There is one more element you will add to the Flash stage.

  1. Open the file PublishCam.fla in Flash MX.

  2. Close or move the Actions panel so you can access the Flash stage.

  3. Move the PushButton labeled Play Video down about 50 pixels. Use Figure 7.21 for a guide to the layout.

  4. Using the Text Drawing tool, add a static text label that prompts the user to add the name of someone publishing a stream.

  5. Below the text label, add a text input field and name the instance of the text input field streamToPlay_txt. The user will enter the name of a participating user to connect with in this field.

  6. Save your Flash file. You just added a way for the user to connect with streams published by other people or even FLV video that already exists on the server. Next you will add the ActionScript required to make this work.

  7. Open the ActionScript window (F9).

  8. Assign the default value to the streamToPlay_txt text box. The default stream will be the username entered in login_txt. Add the following line after the line connecting the peopleList_mc to MyConnection_nc. Make sure the code stays within the appLogin function (before the closing curly brace):

    // copy the name the person entered to the streamToPlay_txt box
streamToPlay_txt.text=login_txt.text;

  9. Scroll to the bottom of the ActionScript, and add a new function to start the subscription stream:

    startPlay = function () {
// insert play code here
}

    This function, as you remember, is invoked by the play_pb PushButton on the Flash stage.

  10. Open a new NetStream channel to the variable play_ns to receive the video. Assign it to the myConnection_nc connection. Place this code in the first line within the startPlay() function:

    // start a New NetStream channel in the myConnection_nc
     play_ns = new NetStream(myConnection_nc);

  11. Attach the play_ns NetStream as the video source for the play_video Video object on the Flash stage. This code follows the new NetStream command within the startPlay() function:

    // attach the NetStream as the video Source
play_video.attachVideo(play_ns);

  12. Issue the play command to plan_ns NetStream. The video input named in the streamToPlay_txt box will start to play. Place this code within the startPlay() function:

    // play the movie named in the text input field, streamToPlay
// If the stream is currently being published, then it will play a live stream
// If the stream is not being published, then it will play the recorded stream from time=0
play_ns.play(streamToPlay_txt.text);

  13. Change the Play button to a Stop button by dynamically changing its label and Click Handler. Add the following two lines of code as the last code within the startPlay() function:

    // change the button label, and the click handler
play_pb.setLabel("Stop Playing");
play_pb.setClickHandler("stopPlay");

    The Play() command will start a video to play immediately from the server. If the video is still being recorded, it will display the video as it is being recorded. You will see a live video feed of any video published to the system. This is how you connect to another person's web camera.

  14. The last step is to build the stopPlay() function so you can stop the stream. The stopPlay() function is very similar to the stopPublish function you coded earlier. Add the following code at the bottom of the ActionScript, below the startPlay() function:

    stopPlay = function () {
         play_pb.setLabel("Start Playing");
         play_pb.setClickHandler("startPlay");
         // close the NetStream to stop the play
         play_ns.close();
};

    This function changes the label and Click Handler of the Stop button back to a Play button, and then closes the play_ns NetStream.

Review your new code with Listing 7.4:

Listing 7.4 Updated code listing for PublishCam.fla
// —————————————————————-
// PLAY (Subscribe) Methods
// —————————————————————-

startPlay = function () {
      // change the button label, and the click handler
      play_pb.setLabel("Stop Playing");
      play_pb.setClickHandler("stopPlay");
      // start a New NetStream channel in the myConnection_nc
      play_ns = new NetStream(myConnection_nc);
      // attach the NetStream as the video Source
      play_video.attachVideo(play_ns);
      // play the movie named in the text input field, streamToPlay
      // If the stream is currently being published, then it will play a live stream
      // If the stream is not being published, then it will play the recorded stream from
  time=0
      play_ns.play(streamToPlay_txt.text);
};

stopPlay = function () {
      play_pb.setLabel("Start Playing");
      play_pb.setClickHandler("startPlay");
      // close the NetStream to stop the play
      play_ns.close();
};

That's it! You are ready to test the movie once again. This time, invite some friends to come join you. Log into the application, and accept the camera warning. You will immediately see your camera's view. Click Record to start the publishing stream. Click the Play Video button (notice your name is automatically inserted into the input box). You will see a loop back of your signal from the server. This is a live video feed.

To access the recorded feed, stop the playback and stop the record. Start the playback again, and you will see the recorded video of yourself.

Stop all feeds in your application. Start up the recording stream. On your test Computer B, connect with the application and start recording the stream. This time, enter the name of Computer A into the streamToPlay_txt box. You will immediately be connected with the live stream (see Figure 7.20)!

Figure 7.20. The final project displaying a publish stream and a live stream from another computer.

That's the end of this exercise. Be sure to review what is happening in the App Inspector. You will notice two streams being used for each user playing and recording. This example clearly demonstrates how you can channel multiple NetStream instances within a single NetConnection.


Summary

NetStream is certainly one of the most visually exciting elements of the Flash Communication Server, but it is not the most powerful. In the next chapter, you will learn to share data between Flash players. It doesn't sound exciting, but consider the power of playing a video game over the Internet through the Flash player, or consider building a collaborative to-do list over the Internet.


Chapter 8. STEP 8: Collaboration with SharedObject()

If you think you've seen everything, take a deep breath because the information presented in this chapter will compound your possibilities. The power of Macromedia Flash Communication Server MX lies in the new and powerful scripting architecture, SharedObject. SharedObject is a synchronized data storage and messaging structure that employs a standards-based object-oriented programming model. SharedObject was introduced originally in the release of Macromedia Flash MX and is very similar in context to any ActionScript object model.

When used with the Flash Communication Server, a remote SharedObject is used to store data on the server. Being on the server, each Flash player client has access to the data structure stored within it. This object is the cornerstone behind the Communication Server architecture because of its unique synchronization event. When data within a SharedObject is added, modified, or deleted, each Flash player connection can be immediately synchronized with the change. The best example is a simple chat tool. A chat tool uses the remote SharedObject to enable each Flash player to append data to the collective data store. When a new message is added, each connected Flash player is updated with the change.

SharedObjects are also available without using the Flash Communication Server. The local SharedObject is very similar to an HTML cookie. This SharedObject is written to the hard drive of the client computer. If the SharedObject is persistent (meaning it doesn't get deleted), it can be accessed whenever the Flash player is run. The privacy window that appeared when your camera was accessed in Chapter 4, "STEP 4: Simple Chat and Video Conferencing," appears again when you use local SharedObjects. This is a feature of the Flash player that allows a user to allow or deny this activity plus limit the hard disk memory available to the Flash player.

Persistence with a Remote SharedObject allows data to exist even if there are no connections. A Flash player can be resynchronized after a period of disconnect using a persistent SharedObject. Data in persistent SharedObjects are actually stored in an FSO file on the server within a folder created by the server called SharedObjects. This folder is stored within the application instance folder. Storing the data in a file allows the data to persist when all clients have disconnected or even after a reboot of the server! Remote SharedObjects can also be non-persistent and are allocated to temporary memory spaces on the server. When all clients disconnect, the application is reloaded, or the server reboots, these SharedObjects are deleted.


SharedObject Methods

The SharedObject architecture has a powerful series of methods. Its only property, data, allows you to set ActionScript variable types including objects and arrays as slots. There will be more on the definition of a slot later. The most powerful component of the SharedObject, however, is the onSync method. This method is responsible for handling data-change messages used to synchronize all clients connected to the Remote SharedObject. Here is a brief overview of the SharedObject ActionScript. The details of these ActionScript items are presented within the exercises of this chapter.

.close()

This method closes the connection between the Flash client and the server. If the SharedObject is persistent, when the client reconnects, it receives synchronization events from an information object sent from the server. If the SharedObject is not persistent, and this is the only (or last) client connected, the object is deleted.

.flush()

This method is used in tandem with a local SharedObject, which is always persistent. When used, it transfers data stored in the local SharedObject to the file specified by the getLocal() method. This book doesn't review details about the local SharedObject.

.getSize()

This method returns the size of remote or local SharedObjects. It is important to monitor size when using local SharedObjects due to the ability for the client to set the maximum allowable disk space independent of your Flash movie.

SharedObject.getLocal()

This method instantiates the local SharedObject to an ActionScript variable. It takes two parameters (the name of the object and the file path) to store it on the host computer.

Note

The following methods are only available with Flash Communication Server.

SharedObject.getRemote()

This method instantiates the remote SharedObject to a local variable. It must be used before the connect() method to declare the name of the SharedObject on the server, the application/instance details, and if it will be persistent or temporary.

.connect()

This method associates the remote SharedObject with a pre-existing NetConnection. This method must be used before a remote SharedObject can be written to or accessed.

.send()

This method invokes a function handler defined in the SharedObject on each connected client. This process is known as broadcasting a message over the SharedObject. Functions that are defined in the remote SharedObject at the client or server can be called using send(). Popular uses might be triggering a sound effect or altering the client's movie somehow.

.setFPS()

This is not frames per second; however, you can use it as a good analogy. This function declares the frequency of communication between the Flash player and the server, also known as updates per second. The higher this value, the faster the response by the client to the server. A value of (0) turns off any updates to the server and forces the user to invoke the update.


SharedObject Property

The .data property stores information within ActionScript variable types, known as attributes or slots. You cannot write a value directly to the .data property, but you can create collections of attributes. Each attribute could be an object, array, or any type of ActionScript variable. When values are changed within the attribute (or slot), Flash Communication Server announces the change to every connected client sending the name of the changed attribute to the client. This announcement is handled by the ActionScript onSync event.


SharedObject Events

The events of the SharedObject make it unique from any other ActionScript object. There are two events: onStatus and onSync. The onSync method informs each client to update itself with changes or additions made to the remote SharedObject.

.onStatus

onStatus is just like any other onStatus you have been introduced to. Each time the remote SharedObject receives an error, warning, or other informational note, this event is triggered. The data is received through an information object containing multiple properties including code and level. onStatus can only be overwritten after instantiating the SharedObject, unless you choose to overwrite the prototype. A full listing of all Information objects handled by onStatus is presented in Appendix C,"Information Objects (Server and Client) Quick Reference."

.onSync

onSync handles announcements sent from the server. These announcements inform the client of changes made to an attribute of the data property. Like onStatus, this event must be overwritten to handle these announcements. The server sends an Information object containing an array of objects that have been changed, added, or deleted. ActionScript must be created to handle these announcements. onSync will be discussed in great detail later in the section "How Does the Shared Cursor Work?".

Exercise 8.1: Using the Remote SharedObject with the Macromedia Flash Communication Server MX UI Components

Let's jump right into a simple implementation of a remote SharedObject first using some of the Flash UI components that were installed in Flash MX. There is no new scripting involved with the first example. You could even do this using the SimpleConnect component. Following this exercise, you will learn what is happening between the server and the client.

You have already used SharedObjects with some of the previous exercises in this book. Did you know the Chat UI component used a persistent SharedObject to store the logs of your chat? This is why you can continue to see the logs, even after reconnecting after a disconnection. Two very obvious implementations of SharedObject can be demonstrated using the Cursor component and the WhiteBoard component. These two objects allow you to see the mouse position of each connected user and draw on each other's Flash player windows. They can both be used with the SimpleConnect component, but to continue with our scripting theme, we will use the Login button you used in the previous examples.

First, begin working on the server. Set up a new application folder:

  1. Open the folder containing the applications on the Flash Communication Server.

  2. Create a new application folder called mySharedApp.

  3. Copy the file main.asc you created in the mySecondApp folder. If you didn't create that file, refer to Chapter 6, "STEP 6: ActionScript with NetConnection()," for the details of that file.

That's all you need to do on the server. This exercise builds on the Step2-multiConnect.fla file you built in Chapter 6 . Copy the file Step2-multiConnect.fla to the new mySharedApp folder (or your work folder) and give it the name WhiteCursor.fla. Use Figure 8.1 as a guide for your layout of the UI components. With the application folder setup, follow these next steps to construct the interface:

  1. Open the work file WhiteCursor.fla in Flash MX.

  2. Drag the Cursor UI component from the Communication Components panel (Ctrl+F7) to the Flash stage. This adds a dot to the screen. It doesn't matter where the dot is. It represents an "empty" MovieClip.

  3. Click the Cursor dot and give it the instance name cursor_mc in the component Properties window.

  4. Create a new layer on the Timeline.

  5. Drag the new layer to the bottom of all other layers. This layer will be used for the Shared WhiteBoard. You must put it on a layer "under" the other objects on the Flash stage.

  6. Click the first frame of the new layer.

  7. Drag the WhiteBoard component to the Flash stage.

  8. Name the component whiteboard_mc. Make sure you select it first to see the component properties!

  9. Set the following properties in the Properties window to make the WhiteBoard full screen:

    W: 550

    X: 0

    H: 400

    Y: 0

  10. Open the ActionScript panel (F9) and click on the frame containing the ActionScript (default: Frame 1; Layer 1).

  11. Change the application reference from mySecondApp to mySharedApp in the NetConnection string. Confirm the ActionScript with Listing 8.1.

    Listing 8.1 Completed ActionScript Listing for WhiteCursor.fla
    // create a new instance of the NetConnection object
myConnection_nc = new NetConnection();
// handle any status changes and responses from the server
myConnection_nc.onStatus = function(info) {
      trace("LEVEL: "+info.level+"  CODE: "+info.code);
};
// connect the application when the Login button is pressed
appLogin = function () {
      // Make the connection to the server
      myConnection_nc.connect("rtmp://192.168.0.112/mySharedApp/myInstance", login_txt.
  text);
      // Connect the UI Components to the new connection
      peopleList_mc.connect(myConnection_nc);
};
connectionLight_mc.connect(myConnection_nc);

  12. Connect the Cursor and WhiteBoard components with the myConnection_nc connection. Place the following code under the peopleList_mc connection line:

    cursor_mc.connect(myConnection_nc);
whiteBoard_mc.connect(myConnection_nc);
    Figure 8.1. The WhiteBoard and the Cursor UI components use SharedObject to display their activity on remote computers.

These Flash UI components are very easy to connect. You don't even need to use ActionScript if you choose to use the SimpleConnect component. Invite someone to test the movie with you. Publish the movie (F12) and log in to the application. The Cursor component creates a simple "avatar" that represents you on the screen. The WhiteBoard component allows you to collaborate on a drawing. The WhiteBoard is a great starting point for the application. Consider if you placed an image below it. You could build a simple annotation system. If you placed a live video feed under it, you could also annotate live video, while having a conversation with someone.


How Does the Shared Cursor Work?

The Shared Cursor traces your mouse movement using Flash's onMouseMove method. The component copies the x,y values to attributes within a remote SharedObject. When the data is copied, other Flash players are notified and can re-create your mouse and position. This allows you to "track" the mouse activity of connected users. Each user has a slot created within the SharedObject on the server. When data changes within the slot, notifications are sent to each connected client. The notifications are handled by the Flash player by setting the local x,y property to the value of the changed slot (or user). It's a handy tool that uses a simple concept and a great technique for handling data on the server. More will be discussed on the slot concept and the structure of the SharedObject after the next exercise.

The WhiteBoard uses Flash's drawing methods to create arrows and text annotations on the Flash stage. Other Flash players that are connected can see what is happening and add their annotations. Although there is a lot more going on with this application, the basic principle is the same. Each time a line is drawn the WhiteBoard component dynamically creates a new slot within the SharedObject on the server. This is why you can click a line and move it around. This process calls a series of special WhiteBoard methods that draw the new object on other Flash players.

We won't get into reverse engineering the components, but it is important to understand how it all works. In Exercise 8.2, you will use the SharedObject to share MovieClip properties, but first let's look into how the Flash Communication Server synchronizes everything.


Synchronization

The Shared Cursor is a great component to demonstrate synchronization using the Flash Communication Server. The concept is this: When data changes, everything connected to the application (with security) must respond to the change. That response is completely up to you. Macromedia has used the object framework to allow you ultimate flexibility in handling data change.

There are at least two relationships that you can achieve with synchronization. These forms relate to how you set up the application. A subscriber/publisher relationship can have two forms. A one-way format has no interaction. This is similar to a presentation or a TV-type show with no return channel to receive input from the remote players. Another format for this relationship is similar to a classroom model with a group of students and a teacher facilitating a discussion. The teacher controls time where the participation is a one-way discussion and times where students can interact (multiple-way). Both formats in this relationship usually have two separate Flash movies communicating with a common Server application instance. One Flash movie would have publishing controls built-in such as enabling NetStream publishing for video conferencing, or moderating discussion for a chat window. One very common approach is running a slide presentation, where one Flash movie has the capability to advance slides and publish an audio video stream, while a second (public) Flash movie cannot do anything but watch the presentation.

A collaborative relationship features a format where everyone connected can control everything. The previous exercise is a good example of that. Everyone was able to control the WhiteBoard yet maintained sole control of her mouse pointer. This form of communication is perfect for games or collaborative working environments. Socially, it requires the most diplomacy within a group, but that's a whole other chapter.

How does Flash Communication Server actually do the synchronization? The server treats each change of the SharedObject as an event. Within Flash MX, the SharedObject uses a new event handler, onSync. The .onSync event handler is triggered when the server announces a change to a SharedObject. In the case of the cursor component, your mouse movement writes the x,y values to the SharedObject. So, every time a mouse is moved, data on the server is changed, and the server announces that change to every Flash player that is connected, including the one that made the change.

The .onSync method is invoked by every Flash player when the server sends these announcements. Every connected Flash player receives an Information object containing an array of objects, each with three properties. The array length is equal to the number of data attributes that changed on the server. This architecture is what allows you to support "disconnected" clients, such as mobile devices, where connection times are short and intermittent. For example, when a mobile device connects to the server, it synchronizes itself using the .onSync event looping through the array of objects sent by the server.

Each object within the array only carries three parameters. These parameters describe the change to the data. They do not contain the data. It is up to you (using ActionScript) to review the objects and retrieve the data as they describe. The three parameters are code, name, and oldValue. These are important to understand, so let's get into some further detail.

Code

The value of the code parameter is the controller. You base your actions on its value. There are five possible values that code can have:

  • Success This value is received by only the Flash client that successfully made the change to the SharedObject. When your application receives this request, usually you ignore it because the change was already made on your player, or you message the user that the update was successful. It is like resetting the cursor x,y values each time you move the mouse. It is not required.

  • Change This value is received by each Flash client that did not make the change to the server. You use this value challenge to invoke the changed property values to the Flash client.

  • Reject This value is received by only the Flash client that unsuccessfully tried to make a change to the SharedObject. This is usually the case when a collision happened, where two clients tried to write to the same property at the same time. If this happens, consider locking the SharedObject. This will be explained in Chapter 14, "Server Administration."

  • Clear This value is received by a Flash player that connected to a SharedObject for the first time. When using a temporary SharedObject, the SharedObject only persists as long as it is being used. This value can be used to invoke a process of initialization to create initial object structures and values on the server. Clear is also sent if the server and client data are so far out of sync that the client dumps its version of the SharedObject and resynchronizes itself completely.

  • Delete This value is returned to all Flash players when an object has been deleted.

Name

The name value describes the name of data attribute (or slot) that was changed within the SharedObject. To access the data, ActionScript contacts the server to retrieve the value(s) of each changed data attribute. If the data attribute was an object, you must know the architecture of the object to retrieve the information. If the attribute was an array, you retrieve the entire array and resynchronize it with the local data. The data attribute can be any of the basic ActionScript or JavaScript types including strings, numbers, Boolean, arrays, or objects. It is in the data attribute that you must have a strategy planned for data storage. You do not want data on the server that you do not plan to share.

OldValue

When the code property returns reject or change, this parameter contains the former value of the changed object. This allows you essentially to "override" the change and revert the attribute back to its previous value.

Warning

The onStatus event is not triggered if an identical value is written to a SharedObject data attribute. If you write a value of Hello World to an attribute that already contains the string "Hello World", onStatus does not run.


Implementing SharedObjects

When you consider the possibilities of data you can share within Flash new business models, technology and user experiences will develop quickly.

Consider affecting MovieClip properties on the Flash stage. Every object placed on the Flash stage has an x and y property. The value of these two properties describes the position of the MovieClip registration mark. Storing the values of the x,y properties in a SharedObject would allow you to share that data to every Flash player. You could write ActionScript to have that MovieClip respond to any changes in that data. You would end up with a MovieClip that shares its x,y position with the world. When Computer A moves the object, every Flash player connected would see the object move.

Consider sharing text data. The most obvious execution of this is live chat. Let's break down how a chat works. Within a single SharedObject, there might be a property called chatData, which contains the chat's log. Each time a user adds a message, the new message is appended to the chatData property. This will invoke the onSync handler on each client connected to the SharedObject.

The Flash Communication Server is really a framework at your command. You can develop any functionality you want. You can have many different versions of a Flash movie interact within the same instance of a Flash Communication Server application. The Flash UI components give you a starting point; you conceive the idea and implement it.

Let's step it up a notch by adding a database to this. Let's say you are writing a business application that allows multiple accountants to interact with data through some sort of spreadsheet-type solution. This next exercise will explore the implementation of a custom SharedObject. Using a MovieClip, you will share four properties of that MovieClip among everyone connected. You will also add the Chat UI component, just because you can and it's easy.

Exercise 8.2: Implementing the Remote SharedObject

In this exercise, you will connect a remote SharedObject to your application. This is your first coding of the SharedObject, so this exercise starts out easy with simple data attributes. This movie will allow multiple people to log in, chat, and collectively modify the properties of a MovieClip on the Flash stage. It is an excellent example to demonstrate the use of the remote SharedObject. Use Figure 8.2 as your layout guide for this exercise. The Maple Leaf is available from the book's web site.

Figure 8.2. The final output of this exercise shows three UI components in use with custom scripted SharedObjects.

This sample will be built on top of Exercise 8.1 within the mySharedApp application folder. If you did not complete Exercise 8.1, please review it first.

  1. Open the previous example, WhiteCursor.fla, in Flash MX.

  2. Save the file as ShareClip.fla in a folder accessible by multiple computers.

  3. Place a Chat UI component on the Flash stage. With the component selected, give it the instance name of chat_mc.

  4. Open the ActionScript panel (F9).

  5. Confirm your ActionScript with Listing 8.2.

    Listing 8.2 The Existing ActionScript for ShareClip.fla
    // create a new instance of the NetConnection object
myConnection_nc = new NetConnection();
connectionLight_mc.connect(myConnection_nc);

// handle any status changes and responses from the server
myConnection_nc.onStatus = function(info) {
      trace("LEVEL: "+info.level+"  CODE: "+info.code);
};

// connect the application when the Login button is pressed
appLogin = function () {
      // Make the connection to the server
      myConnection_nc.connect("rtmp://192.168.0.112/mySharedApp/ myInstance", login_txt.
  text);
      // Connect the UI components to the new connection
      peopleList_mc.connect(myConnection_nc);
      myChat_mc.connect(myConnection_nc);
};

  6. Connect the Chat UI component chat_mc below the peopleConnect_mc connection within the appLogin function.

  7. Test your code using the ActionScript Code Tester (Ctrl+T) or click the checkmark at the top of the panel. If your script has formatting errors, review the output panel (F10) for details. Before continuing, ensure there are no errors reported. When no errors are returned, a dialog box appears as shown in Figure 8.3.

    Figure 8.3. Using the Test ActionScript feature in Flash MX is a handy way to ensure your code is correct before adding increased functionality.
Step 1: Build the Flash Interface

These next steps will build the Flash interface for the exercise. You should already have the three login elements (prompt, input box, and PushButton): the PeopleList, the ConnectionLight, and the Chat UI component on your Flash stage. Use Figure 8.4 as a visual guide to lay out your Flash stage. Here's how to create your interface:

Figure 8.4. Lay your Flash stage out in a similar fashion to this figure.

Let's start by first arranging your Flash stage similar to the example in Figure 8.4.

  1. Create or import a graphic to the Flash stage. This is seen in the figure as a big maple leaf. You can also use the drawing tools to create an object on the stage. Try to size the object similar to the size of the leaf on this stage.

  2. Select the object and convert it to a MovieClip by pressing F8 or selecting Insert, Convert to Symbol. This allows you to control the object using ActionScript.

  3. Name the instance of the object leaf1_mc in the Properties panel. Remember, you must have the object selected before you can change its properties.

  4. Create four static text labels using the Text tool to prompt the user. The labels should read as follows:

    Rotation:

    Width:

    Height:

    Alpha:

  5. Create four input text fields using the Text tool. These will be used to allow the user to change the properties of the MovieClip.

  6. Name the instance of the input fields in the Properties panel as follows:

    lf1_rotation_mc

    lf1_width_mc

    lf1_height_mc

    lf1_alpha_mc

  7. Add a border around the MovieClip and the text fields similar to what you see in Figure 8.4. This is not required, but it helps visually separate the screen.

Your interface is now complete.

Step 2: Set Up the Remote SharedObject

Now set up the remote SharedObject. There is a certain sequence of events that you must follow when using SharedObjects. That minimum sequence is as described here:

  1. Instantiate the NetConnection.

  2. Connect the NetConnection.

  3. Instantiate the remote SharedObject.

  4. Set the name, client, and persistence.

  5. Connect the SharedObject instance. (This is very important.)

  6. Overwrite the onSync handler.

If you have problems connecting with the remote SharedObject, always return to the preceding list to compare your sequence with this sequence. A common omission is connecting the SharedObject to the NetConnection. This is just like connecting a NetStream with the NetConnection. You must tell the SharedObject where it is coming from. In the preceding sequence, there are no onStatus handlers. I recommend that you include the onStatus handlers after instantiating the NetConnection and the SharedObject objects; however, it is not a required step.

The SharedObject in this exercise is instantiated and connected within a new function called initSharedObject. The onSync function also is overwritten within this function. The reason a function is used is because the NetConnection cannot be established until the user logs in. Having these commands within a function allows ActionScript to set up the object after the connection has been made. Let's build the ActionScript to construct the process:

  1. Create a new function that contains the SharedObject connection and onSync event. Insert the following code after the appLogin function:

    initSharedObjects = function () {
// Place all code in the next steps within this function
};

  2. Instantiate the remote SharedObject to a local variable using the SharedObject.getRemote() function. This function takes three parameters. The object name as the server and all connected clients will see it. The URI containing the server and application information is where the object will be stored. This is easily captured using the NetConnection property nc.uri();. The last parameter defines a Boolean value (true or false) for the persistence of the object. If this parameter is not included, its default is set to false. This means the object is a non-persistent or "temporary" object.

    //
// Setup the Remote SharedObject
//
this.so = SharedObject.getRemote("canShare", myConnection_nc.uri, false);

    Use the this. reference to ensure it is set to the caller (in this case, the _root). You could also use a _global setting for the SharedObject variable.

  3. Connect the SharedObject to the pre-established NetConnection:

    // Connect the new Remote SharedObject to the NetConnection
this.so.connect(myConnection_nc);

  4. Overwrite the onSync handler. This is exactly the same as overwriting the onStatus handler. This function is called when the server announces a change to any data attributes within this SharedObject. The information object containing the array of objects that need to be synchronized is stored in the info variable:

    // Setup the Synchronization handler
this.so.onSync = function(info) {
   // place your handler code here
   // Begin Syncing
   trace("updated");
};

We are going to stop there and leave the development of the onSync function until we develop the code to write the changed values to the SharedObject.

Step 3: Write the Changed Values to SharedObject

These next steps will construct the ActionScript required to change the data properties of the SharedObject:

  1. Add the following code listing below the initSharedObjects() function. This ActionScript is actually one script duplicated four times. You could write a function that would automatically develop these functions, but you will do that in another exercise. Using the text.onChanged event, these functions will respond each time the text input box is modified. This means that the user does not have to press Enter to submit the changed information. When you are finished, you will notice that the MovieClip changes size, rotation, and alpha each time you enter a number. For example, typing the number 100 in the rotation box changes the rotation of the MovieClip to 1, then to 10, then to 100. Each function in the following code is calling a custom function, changeClip(), that hasn't been built yet. The function changeClip takes two parameters: the property to change and the value to change it to:

    // Rotation Text Input
lf1_rotation_txt.onChanged = function() {
      changeClip("_rotation", lf1_rotation_txt.text);
};
// Width Text Input
lf1_width_txt.onChanged = function() {
      changeClip("_width", lf1_width_txt.text);
};
// Height Text Input
lf1_height_txt.onChanged = function() {
      changeClip("_height", lf1_height_txt.text);
};
// Opacity Text Input
lf1_alpha_txt.onChanged = function() {
      changeClip("_alpha", lf1_alpha_txt.text);
};

  2. Create the changeClip function. This function has two roles. First, it writes the updated MovieClip properties to the remote SharedObject, and then it updates the MovieClip on the Flash stage:

    // This method will handle the onChanged events and will dynamically
// set the property of the object locally.  It will then update the SharedObject
//
changeClip = function (property, new_value) {
      this.so.data[property] = new_value;
      leaf1_mc[property] = new_value;
      trace("property: "+property+"    value: "+leaf1_mc[property]);
};

    What's leaf1_mc[property]?

    The ActionScript leaf1_mc[property] may be an unfamiliar style of setting a MovieClip property. You look at this and ask yourself, "Why didn't we use Flash's setProperty method?" as in the following line of code:

    setProperty(myMovieClip,_rotation,50);

    The immediate answer is that Macromedia will be deprecating the setProperty and getProperty functions. They still work, but are left over from previous versions of ActionScript. The real reason they are used is that setProperty() wouldn't work. In our situation, the property value must be dynamic, and the setProperty() method does not support dynamic property names. This alternative accomplishes the exact same thing, but allows us to pass the property as a variable. setProperty is included in Flash MX primarily for backwards compatibility when it was introduced in Flash 4.

    This line of code achieves the same thing as the getProperty method; however, here we can substitute the property with a dynamic variable:

    myMovieClip["_rotation"] = 50;

    Most people are familiar with the dot syntax. The same command could be given like this, but this format also does not support dynamic assignment of the property:

    myMovieClip._rotation = 50;

    In modern Flash applications, you should resist using the getProperty or setProperty methods and go with either the dot syntax or the bracketed, "key" syntax. Any function will add additional CPU cycles, plus these alternatives offer more flexibility. For example, with the bracket syntax, you can make the property a variable by replacing the string value with an ActionScript variable type.

    This is a clever little helper that saves you a lot of ActionScript coding. It receives two parameters from the onChange handler you coded in the previous step for each text box. The first parameter is the name of the property to change, the second is the value to change it to.

    Writing to the remote SharedObject is pretty straight forward. In this case, we are using the name of the MovieClip property (_rotation, _height, _width, and _alpha) as new attributes of the data property. You can say that our SharedObject has four attributes; each attribute is of type number. Simply writing to the SharedObject invokes the server to announce the changes to all connected clients, invoking their onSync handlers. There will be more discussed about this after the exercise.
Step 4: Finish the onSync Handler

Let's build the onSync handler for this SharedObject.

The following code ultimately is placed within an array loop to handle multiple attributes being synchronized. This code also is placed within a challenge (IF statement) of the code parameter, but for now, you do not place that in and only synchronize the first object in the array:

  1. Access the name parameter of the code object in the first array position. The array of objects was passed into the info variable. To access the first position of the array, use info[0]. Access the parameter of the object by name, in this case name. This value provides the name of the attribute that was changed:

    // transfer the name of the changed attribute to the var "property"
var property = info[0].name;

  2. Access the data element stored in the property variable set in the previous step:

    // transfer the value of the changed property to the var "newValue"
var newValue = this.data[property];

  3. Change the property of the MovieClip, leaf1_mc, to the synchronized value. Notice how we use the name of the attribute as the property name. Doing this saves a couple lines of code, plus it will save some bandwidth:

    // Sync the MovieClip property(_rotate, _width, _height or _alpha)
leaf1_mc[property] = newValue;

  4. Set the value of the input box to the new synchronized value. Again, this must be done a special way so that one line of code could set any one of four possible text input boxes. This was strategic planning in the earlier decision to name these text boxes relevant to the properties they are changing:

    // Update the input boxes with the sync value
_root[""lf1""+property+""_txt""].text = newValue;
Step 5: Call the initSharedObject() Function

This section will call the initSharedObject() function when the user logs in:

  1. Move the cursor into the appLogin() function.

  2. Add the following line to call the SharedObject just before the closing curly bracket at the end of the function:

    initSharedObjects();

At this point, your code is ready to be tested. It is not yet complete; however, to keep the exercise simple, go ahead and test it now to demonstrate how it is working.

You can test this application on a single computer running multiple windows of the same application. You might find it fun, however, to open the application on multiple computers. Give a friend a call, and if possible, have him access the application from outside your network. In preparing this example, our testing environment included five people from all over the planet. Each participant was able to test manipulating the leaf at the same time.

Step 6: Refine the Synchronization Process

The final step to this whole process is refining the synchronizing process. Right now, only the attribute mentioned in the first object will be synchronized. You must develop a loop to run through each object in the array. It was mentioned earlier that you need to handle the code parameter for each object in the array. So, inside the array loop challenge the code property using a simple IF statement, or in Listing 8.3, using the Switch/Case method. The entire block of code currently in the onSync handler is code that should only be executed when the code value equals "change".

Listing 8.3 is a great prototype for you to handle all of your onSync events in any of your applications. Using the Switch/Case condition is a developer-friendly way (easier to read) to handle a long IF/ELSE method. Replace the entire onSync function you wrote with this one. Take note that the actual code you wrote hasn't been altered, it has only been placed within the case when the value of code is "change". Having this code in place allows your applications to disconnect and become synchronized when they reconnect. It also handles bandwidth more efficiently and does not update the stage where the changes originated.

Listing 8.3 Handling the onSync Event
this.so.onSync = function(info) {
      trace("Syncronizing Data");
      //
      // Use this structure as a prototype for your onSync Handlers.
      // Loop through the Array of Objects using the IN operator
      //
      for (name in info) {
            trace("[sync] Reading Array Object #"+name+"  code ("+info[name].code+",
  "+info[name].name+")");
            //
            // ::: The following switch handles the code values returned by the object
            // Place Code Here
             switch (info[name].code) {
             case "change" :
                    trace("::Synchronize data changed from outside the Flash Player");
var property = info[0].name;
                    var newValue = this.data[property];
                    leaf1_mc[property] = newValue;
            _root[""lf1""+property+""_txt""].text = newValue;
                    break;
             case "success" :
                    trace("::Handle a successful change of server data from this player");
                    // Place Code Here
                    break;
             case "reject" :
                    trace("::Handle a rejected SharedObject write operation");
                    // Place Code Here
                    break;
             case "clear" :
                    trace("::Handle an initialization of the SharedObject");
                    // Place Code Here
                    break;
             case "delete" :
                    trace("::Handle deleted Attributes");
                    // Place Code Here
             }
              // ::: End the Switch, continue Looping through the Information Object
       }
       // ::: Complete the onSync Handler
};

Note

A listing of the full ActionScript is available on the web site mentioned at the beginning of this book.

Testing your movie within the Flash MX environment lets you see any trace activity in the output window. In Figure 8.5, the output window is showing a reconnect to the application. You can see the player looping through the array handling three objects. Two objects describe the change in the _width and _rotation attributes, and one object has sent a clear command.

Figure 8.5. The Flash MX output window displays your trace output. This is a handy tool for debugging, but it's not the only one. Flash MX ships with an interactive Debugger. Chapter 12, "Client-Side (Flash) ActionScript," will review the use of that debugger.

This output window is also showing that a remote player has made a change to the _rotation attribute, and this player has reset its _rotation property to the new value of 80. You can also see that this player has made a successful change to the _rotation attribute, and it was broadcast to every connected player.

This is a great exercise to help you understand how the Flash Communication Server handles synchronization. Because this framework is so open, you can build very powerful communication applications that can share extremely complex and confidential information. For some advanced implementations of this technique, be sure to read some of the tutorials at the end of this book. In particular, review Chapter 17, "Making Faces: The Living Emoticon."

The next section will describe the idea behind a slot as it relates to the SharedObject.data attributes.


Data Management Using Slots

The data attributes of a SharedObject (or slots) can contain any basic ActionScript or JavaScript variable type. Two of the most common types include arrays and objects because of their capability to store organized complex data. You will get the most benefit from Flash MX and the Flash Communication Server if you understand basic object-oriented programming used in ActionScript and JavaScript. The full scope of the object model is very powerful, but understanding the basic model for data storage is simple. Figure 8.6 is a simplified overview of how you can use slots within the data attribute.

Figure 8.6. How the data attribute can store a collection of ActionScript variable types.

In Flash circles, the term slot could be a property of a MovieClip. Or in the case of the SharedObject, a slot refers to a variable slot off the data attribute. These slots are what the Flash Communication Server monitors for change. In the previous exercise, simple variable slots are used to store the shared properties of the MovieClip. We could have placed these properties within an object; however, Flash Communication Server would report that the entire object had changed each time a property value was modified. It was much more efficient to use a different slot for each MovieClip property. Using this method, significant bandwidth was saved.

Consider a more complex example. Let's say you contain an object with 10 properties within an array position. This is very similar to structure of the information object handled by the onSync method. Each time a property within any embedded object is changed, the server announces a change to the entire stub (which in this case is the entire array). Each Flash player then is responsible for downloading the entire array and parsing it to reflect the change.

You are seeing now the need for some data management. That is a strategy you are responsible for planning. Chapter 15, "Communication Application Architecture Strategies," will discuss some strategies for handling larger amounts of data using the SharedObject architecture.

Objects—Properties—Values: Understand This Model

The relationship between objects, properties, and values is important to know, especially when bandwidth becomes an issue. Read the case below to help you understand the lexicon and the concept of objects in programming.

Consider a cardboard box as an object. This box has properties that include height, width, weight, volume, and so on. Each property has a value. Height = 5 inches, width = 10 inches, weight = 5 lbs, and volume = 500 cubic inches. Some properties, such as height and width, cannot be changed without a pair of scissors and some duct tape. When you put something into the box, this changes the value of its weight property.

Now, put this into the context of synchronization and the Flash Communication Server. The only property that can change with this box object is the weight. When someone puts something in it, the weight changes. If this box exists in the Flash environment, the Flash Communication Server would announce to every Flash player that the box object has changed, with no mention to the property weight. Flash players respond by accessing the box object and retrieving its properties.

How would this look as ActionScript code? There are two ways to set up the box object. These few lines of ActionScript create a new myBox object with four properties, each with initial values:

myBox = new Object();
myBox.height=5;
myBox.width=10;
myBox.weight=10;
myBox.volume=500;

A simplified technique can also be used to set up the initial properties and values of an object using a single line of code. The following example does exactly the same as the previous example:

myBox = new Object({height:5,width:10,weight:10,volume:500});

To make it even simpler, ActionScript automatically declares the variable as a new object when you pass this structure:

myBox = {height:5,width:10,weight:10,volume:500};

Advanced users could develop a myBox prototype containing all the constant values with a method to retrieve the weight property, and then "instance" the box object to myBox. But we won't do that here, just to keep it simple. Transferring the object to a remote SharedObject is easy. Simply copy the entire object to the data property. This example creates a new, non-persistent, remote SharedObject on the NetConnection called myRemoteObject, and then sends the myBox object as a slot of the data property.

// setup the shared object using the "my_Connection" NetConnection.
   my_so = SharedObject.getRemote("myRemoteObject", myConnection_nc.uri, false);
   my_so.connect(myConnection_nc)

// attach the myBox object to the SharedObject
my_so.data = myBox;

You can see that interacting with the SharedObject is just like interacting with client-side variables.

Accessing the remote data is easy using some simple programming techniques. This line of code returns the value of the weight property stored in the myBox object at the server:

var myLocalVar = my_so.data[myBox].weight;

This line of code writes a new value to the weight property on the server:

my_so.data[myBox].weight = myLocalVar;

Deploying some smart SharedObject management increases performance of your application, and decreases the load on bandwidth and server resources. Remember that each time you read/write data to the remote SharedObject, you are communicating over the NetConnection. You should practice conservation by only storing objects and properties that will be known to change. Achieving this technique involves applying some home-grown strategy to the synchronization process. This book will present a few strategies along the way, but you can apply any strategy you wish—that is the largest benefit of object-oriented programming.

Suggestions—What You Can Do with the Remote SharedObject

Remote SharedObjects require the most creative thinking to put them to use. Because they are so flexible, you have a lot of opportunities. Here are some ideas on how you can use the remote SharedObject in your applications:

  • Network games

  • Presentations

  • Internal communication

  • Collaborative workflow

  • Security cameras


Summary

The SharedObject model is a very powerful feature of the Flash Communication Server. Clearly, if you understand object-oriented programming and JavaScript, you will gain a lot in performance and security. The next chapter will put some of what you have learned to use in a larger context.


Chapter 9. STEP 9: Controller and Subscriber Applications

This chapter introduces the controller and subscriber application used to deliver presentations for e-learning, your annual general meeting, or just a family slide show. The controller and subscriber application is a single Macromedia Flash Communication Server application with two parts. One part is for the viewer, the other runs the show, like a speaker or a teacher manages an audience or classroom. Up to this point in the book, you have developed communication applications that are collaborative using a single interface for every user connected to an application instance.

This chapter will introduce you to working with two application parts. The Flash UI components PresentationSWF and AudioConference will be introduced and embedded into a more complex and practical application. You will also learn to use NetStream to broadcast and handle messages to and from other connected Flash players.


Controller Applications

In Chapter 7, "STEP 7: Streaming Video with NetStream()," you were introduced to a model of publication and subscription in the context of streaming video. The controller application operates similar to the streaming subscription model. Controller and subscriber applications use two different interfaces to interact with an application. One interface controls what the other interface can see and do.

To illustrate this model, imagine you were sitting in on a presentation at a conference. The presentation has a speaker on a stage with a PowerPoint (or Flash) presentation on a laptop. You take your seat in the back of the room and enter into a one-way relationship with the presenter and his laptop. During a presentation, the speaker is positioned on a stage in front of an audience of attendees. The speaker controls what the audience can see on a screen and manages when questions can be asked or answered.

Using multiple Flash user interfaces connected to a single application instance, you can build applications with the Communication Server to handle a relationship like this. Multiple Flash user interfaces can be integrated into a single Flash movie or completely separate movies altogether. Each unique interface plays a role in the application.

For example, in Exercise 9.1 you will build two interfaces. One interface will control how the other (subscribing) interface will act. For example, the controller will feed the subscriber presentation slides and a video feed. This relationship is also useful to distribute a single live video stream to multiple receivers.

The controller interface is responsible for publishing and managing streams and access to data and interface elements.

The subscriber interface responds to controller messages. The subscriber interface operates as a listener.

If you plan to use the Communication Server to broadcast corporate annual general meetings, online panel discussions, presentations, or even to deliver e-learning applications, a controller and subscriber application is what you should consider. So, be prepared to build two interfaces, and plan the roles and use cases for each interface.

Let's start by getting comfortable with the concept. This next very quick exercise will let you control a MovieClip on the Flash stage of each subscriber movie that is connected.

Exercise 9.1: The Simple Controller Application

This exercise is a quick primer to help you understand the roles of the controller movie and the subscriber movie. It will also introduce you to using SharedObject messaging via the so.send() method.

Step 1: The Interfaces

The first phase in this project is to create the controller and subscriber interfaces.

  1. Create a new Flash Communication Server application folder called mySimpleController.

  2. The controller (controller.fla) has three main elements on it. Use Figure 9.1 as a guide to place the elements on the Flash stage. To start, use the Text tool to draw a text input box in Frame 1 of Layer 1. This box will be used to send an instant message. Give it the instance name controllerMSG_txt.

    Figure 9.1. The interface for the controller movie. Use this as your layout guide when you create the movie.

  3. Still in Frame 1 of Layer 1, add a PushButton from the Flash UI Components panel. This button will be used to turn on a MovieClip called theBall_mc running inside the subscriber.swf movie. Give the PushButton an instance name of ballControl_pb.

  4. In the same frame and layer, add a ConnectionLight from the Flash Communication UI Components panel. Give it an instance name of connectionLight_mc.

  5. The subscriber movie (subscriber.fla) has three main elements, as shown in Figure 9.2. For the first one, use the Text drawing tool to create a text box, make it a dynamic text box in the Properties window, and give it the instance name controllerMSG_txt. This dynamic text box will receive instant messages from the controller application.

    Figure 9.2. The interface for the subscriber movie. Use this as a layout guide.

  6. Next, add the "ball" that the controller movie will turn on and off. Draw a circle using the drawing tools on the Flash stage. When finished, select it and press F8, and make it a MovieClip and press OK. In the Properties panel, give it an instance name of theBall_mc.

  7. Drag the ConnectionLight component from the Communication UI Components panel onto the stage and give it an instance name of connectionLight_mc.

These are two completely separate interfaces, with completely separate assets on their Flash stages. They will operate under a common Flash Communication Server application.

Step 2: Controller ActionScript

Next, let's look at the ActionScript required first for the controller interface, and then for the subscriber interface.

  1. Place the following ActionScript on Frame 1 of Layer 1 in the Controller.fla movie:

    myConnection_nc = new NetConnection();
connectionLight_mc.connect(myConnection_nc);
myConnection_nc.onStatus = function(info) {
      trace("Status Message: "+info.code);
      if (info.code == "NetConnection.Connect.Success") {
            initSO();
      }
};

    This ActionScript establishes a quick connection with the server. We aren't worried about usernames at this point. When the server returns a status of NetConnection.Connect.Success, the initSO() function runs to connect the movie to a Remote SharedObject on Flash Communication Server.

  2. Create the initSO() function:

    initSO = function () {
      // Create and Connect a Shared Object to Broadcast to
      my_so = SharedObject.getRemote("testBroadCast", myConnection_nc.uri);
      my_so.connect(myConnection_nc);
      // initialize the Ball Toggle
      toggleBall_ON();
};

    The temporary SharedObject is connected to the NetConnection. Then a function, toggleBall_ON(), initializes the PushButton on the stage. This function will actually be called by the button when the ball is turned off.

  3. Create two PushButton functions. One will be used when the ball is disabled, and one will be used when the ball is enabled. These functions do two things: They broadcast a message to everyone connected to the SharedObject and dynamically change the label and Click Handler of the PushButton. Use the following code:

    // The pushButton Functions
toggleBall_ON = function () {
      my_so.send("toggleBall", true, controllerMSG_txt.text);
      ballControl_pb.setLabel("Disable Ball");
      ballControl_pb.setClickHandler("toggleBall_OFF");
};

toggleBall_OFF = function () {
      my_so.send("toggleBall", false, controllerMSG_txt.text);
      ballControl_pb.setLabel("Enable Ball");
      ballControl_pb.setClickHandler("toggleBall_ON");
};

    You might be wondering where the ball fits in with this script. There is no ball in the controller interface, just a button to send a signal to a MovieClip (the ball) that exists within the subscriber's interface.

    The Send operation (my_so.send) calls the toggleBall method defined in the subscriber.fla file. The toggleBall function will be written within the local SharedObject variable. SharedObject methods are not stored on the server, they are local to the client. Therefore, toggleBall will not be created on the controller application, only on the subscriber. The method will control the visibility of the MovieClip. There are two parameters sent to toggleBall: the state of the ball, as a Boolean value, and the text inside the controllerMSG_txt text box.

  4. Connect the movie to the server:

    // Connect to the server.
myConnection_nc.connect("rtmp:/mySimpleController/myInstance");

Save and publish, and you're done on the controller side.

Step 3: Subscriber ActionScript

Your next task is to code the subscriber file's ActionScript.

  1. Place the following ActionScript on Frame 1 of Layer 1 in the Subscriber.fla movie:

    myConnection_nc = new NetConnection();
connectionLight_mc.connect(myConnection_nc);
myConnection_nc.onStatus = function(info) {
      trace("Status Message: "+info.code);
      if (info.code == "NetConnection.Connect.Success") {
            initSO();
      }
};

    This first bit of code is identical to the Controller.fla movie's code. It sets up the NetConnection and handles the success code when it is accepted by the server.

  2. Create the initSO method. This, too, is similar, except here you declare the toggleBall method within the SharedObject variable my_so. This will handle the broadcast sent from the controller. Use the following ActionScript:

    initSO = function () {
      // Create and Connect a Shared Object to Broadcast to
      my_so = SharedObject.getRemote("testBroadCast", myConnection_nc.uri);
      my_so.connect(myConnection_nc);
      // connect a handler to the shared object.
      my_so.toggleBall = function(toggle, message) {
            theBall_mc._visible = toggle;
            controllerMSG_txt.text = message;
      };
};

    The toggleBall function turns the visibility of theBall_mc to the value sent by the controller (true or false). Then it sets the text value of the controllerMSG_txt text box to what was sent by the controller.

  3. Connect the movie to the server:

    // Connect to the server.
myConnection_nc.connect("rtmp://localhost/mySimpleController/myInstance");

With the bulk of the coding finished, you're ready to handle the connections.

main.asc ActionScript

A very simple onConnect routine accepts all connections. Place this code within a new main.asc file in the mySimpleController application folder:

application.onConnect =function(newClient) {
      application.acceptConnection(newClient);
}

Save and publish both FLA movies. You can test them both within Macromedia Flash MX, but it can get tricky if you don't have two monitors. You want to run the controller.swf movie and a couple subscriber.swf movies. If you can, try running the subscriber.swf movies on remote computers so you can impress your friends with your wizardry.

Note

Now that you understand how the controller movie works, try to extend Exercise 9.1. You can use this technique to do anything you need to within the subscriber's Flash movie. Control the Timeline, video, sound, anything.


Chapter Project Overview

Let's move on to the bigger application to build your first killer Flash Communication application. The examples in this next exercise use some simple background graphics to highlight the Flash UI components on the Flash stage. Because you now have to address how the interfaces will be used, this exercise will walk through a simple user case. User case studies help to describe what you want the interface to achieve for the user.

The next two exercises in this chapter will collectively build the final project. The project involves building a controller application that will facilitate a synchronized presentation of slides. The project must also send a live video and audio feed of the presenter talking about the slides. Subscribers will have opportunities to talk with the presenter, at the presenter's discretion, of course. Figure 9.3 illustrates what the application will look like for the controller and the subscriber.

Figure 9.3. Exercise preview comparing the subscriber and controller interfaces.

The project is broken into two exercises. Exercise 9.2 steps through setting up your Flash movie to handle three different interfaces. Unlike the previous exercise, this project uses one SWF movie to handle the controller and the subscriber. Exercise 9.3 adds live streaming video from the controller to the subscribers.

The Flash UI components you will use through these three exercises include:

  • PresentationSWF

  • AudioConference

  • PeopleList

  • ConnectionLight

One of the best ways to understand what needs to be done is to look at how the applications will be used.

Controller User Case Study

The speaker accessing the controller application logs in with a special name that triggers the controller interface. This special name is decided at the server.

When the speaker arrives at the controller window, the web camera automatically begins recording, and the default presentation loads on all subscriber interfaces that are connected.

If the user wants to load a supporting movie, there is a loadSWF text field on the screen. The presentation must be available on the server to each subscribed client before it can be loaded.

The speaker can manage when the subscribers can start discussing an issue or topic. The speaker has the control to cut all audio conversations and continue with the presentation.

The speaker can see the name of every user monitoring the presentation, but the speaker cannot interact directly with a particular user.

Subscriber User Case Study

The subscriber logs in with her name. This is a public forum, so all names are accepted by the server. If the name entered is not the name associated with the speaker, the user accesses the subscriber interface.

The subscriber interface does not show the presentation and the video feed until the speaker has logged in. However, the participants are able to converse with their microphones using the Audio Conference tool on the interface.

Exercise 9.2: The Macromedia Flash MX Interface

This next exercise steps you through constructing the interface in Flash MX. It involves no coding.

There are three interfaces you have to construct in this exercise:

  • Login interface to register the user

  • Subscriber interface used by public viewers

  • Controller interface used by the speaker

These interfaces will be assembled strategically on the Flash Timeline. Later, in Exercise 9.3, ActionScript will move the play head, to change the interface presented to the user. The interface will be built to leverage common elements including ActionScript. After all, you have enough to debug, why make it harder at this stage?

Step 1: Prepare the Timeline

Before you set up your interfaces, you have to prepare your Timeline.

  1. Open Flash MX with a new document. Save the document as presentationApp.fla.

  2. Create a new layer (Insert, Layer) on the Timeline.

  3. Name the two layers Labels and Actions, as shown in Figure 9.4. Double-clicking the layer lets you rename it in place.

    Figure 9.4. The Timeline is used to display three different interfaces: login, subscriber, and controller.

  4. Create keyframes on both layers in Frames 10 and 20. To create a keyframe, click the frame on a layer and press F7.

  5. On the Labels layer, add frame labels to the frames as follows:

    Frame 1: login

    Frame 10: subscriber

    Frame 20: controller

    To create the labels, select a frame and change the Frame field in the Properties panel.

Your Timeline should look exactly like Figure 9.4. You will be creating a series of new layers below the Actions layer. Always remember what frame you have selected before you drag components or graphical elements to the stage.

Tip

Keyframes are shown by hollow circles in the frame. When you have ActionScript on the frame, the letter "a" appears above the circle. When you have objects within the frame on the Flash stage, the circle becomes a solid color. Refer to Figure 9.5 to see the different keyframe renderings.

Figure 9.5. The login interface and Timeline setup. The background artwork is optional and is stored in the Timeline folder named BackgroundArt.

Step 2: The Login Interface (Frame: 1)

With your Timeline ready, start constructing the interfaces, beginning with the Login screen.

  1. Create two new layers below Actions. Rename them Login and connectionLight. Note that the extra artwork you see in this presentation is stuffed into the BackgroundArt folder on the Timeline. The artwork has no relationship to the components on the screen. See Figure 9.5 for reference.

  2. Move your Timeline cursor to Frame 1 on the Login layer. Place a Text input box with the instance name login_txt on the Flash stage here.

  3. On the same frame and layer, place a PushButton from the standard Flash UI components. In the Properties window, set Label to Login and Click Handler to appLogin.

  4. Place your cursor on Frame 10 on the Login layer, and create an empty keyframe (F7). This will stop the login from displaying across the other interfaces.

  5. Place your Timeline cursor at Frame 1 on the connectionLight layer. With this frame selected, add a second PushButton from the standard Flash UI components. In the Properties window, set Label to Logout and Click Handler to appClose.

  6. On the same frame and layer, place a ConnectionLight component from the Flash Communication UI components. Give it the instance name connectionLight_mc.

The ConnectionLight and Logout buttons will be available across all interfaces, so there is no blank keyframe required. You also do not need to assign the Logout button an instance name, because ActionScript will not be changing any properties of the button.

Step 3: The Subscriber Interface (Frame: 10)

With the login screen completed, move on to the interface that subscribers will use to view the presentation.

  1. Create three new Timeline layers below the connectionLight layer. Note that the extra artwork you see in Figure 9.6 is stuffed into the BackgroundArt folder on the Timeline. The artwork has no relationship to the components on the screen. Name the new layers PresentationSWF, PeopleList, and AudioConference, respectively.

    Figure 9.6. The subscriber interface and Timeline setup. Use this as a layout guide for the interface. Make sure you know where your Timeline cursor is each time you place an object on the Flash stage. This screenshot also shows you the contents of the BackgroundArt folder.

  2. Create a keyframe at Frame 10 for each new layer.

  3. Place your Timeline cursor at Frame 10 on the PresentationSWF layer. From the Communication UI Components panel, drag a PresentationSWF component to the Flash stage.

  4. Set the properties of the PresentationSWF component in the Properties panel as shown in Figure 9.7:

    Instance name: presentation_mc

    Width: 529

    Height: 308.9

    X: 10.8

    Y: 12.4

    Figure 9.7. The Properties panel for the PresenationSWF component. The component will be larger than your Flash stage when you drag it on to the stage. Resize it to the values in this Properties window.

    The Presentation component is a handy tool to synchronize the playback of prebuilt presentation slides. The Properties panel in Figure 9.7 is displaying the name of the SWF file that will be loaded when the presenter comes online. Creating SWF movies for this component will be described at the end of the chapter.

  5. On the same Frame, add a new embedded Video object: Open the Library panel (F11) and select New Video from the panel's drop-down menu. This will insert a new embedded Video object in the Library. Drag that to the Flash stage.

  6. Give the Video object the following properties:

    Instance name: speaker_video

    Width: 130

    Height: 100

    X: 410

    Y: 12

  7. Place the Timeline cursor at Frame 10 on the AudioConference layer.

  8. Drag the AudioConference UI component from the Communications UI Components panel, and give the AudioConference object the following properties:

    Instance name: audioConf_mc

    Width: 134

    Height: 130

    X: 406

    Y: 118

  9. Place the Timeline cursor at Frame 10 on the peopleList layer.

  10. Drag the PeopleList UI component from the Communications UI Components panel, and give the PeopleList object the following properties:

    Instance name: peopleList_mc

    Width: 134

    Height: 114

    X: 407

    Y: 135

That's it for the subscriber interface. Of course, you are welcome to place these elements where you want, but it is helpful keeping them separated onto their own layers.

Step 4: The Controller Interface (Frame: 20)

The Controller interface is very simple. You only need to add the LoadBox and the AudioChat toggle button. So let's finish it up so we can get to the code.

  1. Below the Audio Conference layer, create a new layer called controller-only.

  2. Create a keyframe (F7) on the Timeline at Frame 20 on the new controller-only layer.

  3. All that's left is to assemble three elements on the Flash stage. Use Figure 9.8 as your guide for placement, and start by adding a text input box with the instance name SWFtoLoad_txt to the Flash stage. This will act as the input box for the user to enter the name of a new SWF movie to use as the presentation. Ensure you have selected the text box as input.

    Figure 9.8. The Controller interface contains two additional elements: the load and the enable AudioChat button.

  4. From the standard Flash UI components, place a PushButton next to the SWFtoLoad_txt and set the following properties in the Properties window:

    Instance name: null

    Label: load

    ClickHandler: appLogin

  5. Place a second PushButton at the bottom of your stage. Set its properties as follows:

    Instance name: chatControl_pb

    Label: Enable Audio Chat

    ClickHandler: appLogin

That's it; the three interfaces are now assembled. You can test your design skills with this interface, or you can download the templates from the book's web site.

Now, the scripting begins. Don't forget to save your work before you move on.

Exercise 9.3: Scripting

The scripting side of this project requires a series of four scripts. The efficiency will be revealed when you realize that you don't have to set up the NetConnection for the three different interfaces.

Step 1: Initialization (Frame 1)

The bulk of the ActionScript for this project exists at the login interface. When the login button is pressed and the server authenticates, the play head moves to the appropriate place on the Timeline. Taking this approach saves time and is prone to fewer bugs than having duplicated scripts. Taking this approach also lets you quickly add elements to both the controller and the subscriber applications.

You will see a messaging technique used in this script between the server and the client. In this technique, the server will authenticate the user and control the play head on the client based on the value sent at the login prompt. Let's review the code in depth.

  1. Open the ActionScript panel (F9) in Expert mode (Ctrl+Shift+E)

  2. Include the required Libraries (the details of the FlashcomCustom.as file are discussed later):

    /* NetConnection Debugger enabling, remove when development is complete */
#include "NetDebug.as"
/* Custom Status Handler Scripts */
#include "FlashcomCustom.as"

  3. Set up the initial application objects. We will use a new global object called session to store data across the application. This script will also set up the NetConnection, the ConnectionLight, and disable the logout button (until it's been connected). Add the following code:

    //
// INITIALIZE THE APPLICATION
//
_global.session = new Object();
myConnection_nc = new NetConnection();
connectionLight_mc.connect(myConnection_nc);
logout_pb.setEnabled(false);

  4. Define the appLogin method that will be invoked by the Login button:

    //
// LOCAL APPLICATION FUNCTION HANDLERS
//
appLogin = function () {
      // Login Button was clicked, make the connection with the server
      myConnection_nc.connect("rtmp://localhost/chapter09/myInstance");
      // setup a session object that will contain information about this user
      session = ({username:login_txt.text});
};

    When executed, this function will request a connection from the server and store the username in a username property of the session object.

  5. Define the appClose method that will be invoked by the Logout button and when the NetConnection status receives a closed code:

    appClose = function () {
      if (myConnection_nc.isConnected) {
            myConnection_nc.close();
      }
      _root.gotoAndStop(1);
      logout_pb.setEnabled(false);
};

    When executed, this function closes the active connection, disables the Logout button, and returns the user to the login screen.

  6. Define the appInit method that will be invoked when the NetConnection Status returns a success code. When executed, the connection has been accepted by the server, but hasn't been authenticated. This function will call a handler, authenticateUser, on the server to determine access privileges. The server will decide if the user is a controller or a subscriber. Add the following code:

    //
// appInit RUNS WHEN THE SERVER RETURNS "NetConnection.Connect.Success" CODE
//
appInit = function () {
      trace(" ** Connected :-)");
      trace(" ** User set to: "+Session.username+".  Authenticating user...");
      // CALL THE AUTHENTICATE USER() FUNCTION ON THE SERVER
      myConnection_nc.call("authenticateUser", new serverRet(), Session.username);
      logout_pb.setEnabled(true);
};

    Let's look at the call method a little closer. It has three parameters: method, Return object, and the username. The method is defined in SSAS in the client scope. This exposes the method to the Flash player.

    The Return object is invoked when the server responds. NetConnection functions are the only remote functions that are able to return a result. Because you are requesting processes on a remote computer, the results will not be immediately available. To deal with this, an object is created with two events: onStatus to handle errors and onResult to handle result sets. The final parameter is a required argument of the remote function.

    When the server process is complete, it returns the role of the user (subscriber or controller) to the object. So let's build the Return object.

  7. This object will be instantiated as a listener to handle the server's response. When the server responds, the internal function, onResult, is called. If an error occurs, the onStatus function is called, and it returns the user to the login screen by invoking the appClose() function. Add the following code:

    // GLOBAL SERVER METHOD HANDLER
//
serverRet = function () {
      // HANDLE SERVER RETURNS
      this.onResult = function(returnVar) {
            trace(" ** :-) Server returned: "+returnVar);
                              session.userRole = returnVar;
                  root.gotoAndPlay(returnVar);
      };

      // HANDLE SERVER ERRORS
      this.onStatus = function() {
            trace(" !! Server method, failed, refer to the App Inspector for trace data,
  closing the connection");
            appClose();
      };
};

    When the server responds successfully, it sends back a variable containing the role the user will play. This role is used to move the play head to the correct interface referencing the frame label using gotoAndStop

  8. Your final step is to stop the play head from moving when the movie is loaded. Use a stop() command at the bottom of the first frame:

    stop();

The first frame and the bulk of this project are now behind you. Before moving on to the subscriber code, let's review the FlashCustom.as file mentioned earlier.

FlashComCustom.as

Earlier in this script, the custom script, FlashComCustom.as, was included. It contains a special onStatus catch-all template presented in Appendix E,"ActionScript Templates Quick Reference." This file is also available for download from the book's web site (http://flashcom.pangaeanewmedia.ca/). Placing the script into an external file makes it easier to quickly reuse across multiple applications. Because there is a lot of trace activity, the code is fairly dense to include when you are developing and debugging in this exercise.

Within the FlashComCustom.as file, two NetConnection status changes are monitored: success and closed. These two events are key in the operation of your application. When the code is success, the function appInit() is called. When the code is closed, the function appClose() is called. Review the following script section; it is included in the FlashComCustom.as script:

</BEGIN EXERPT FUNCTION: onStatus..>
      case "NetConnection" :
            if (infoMessage_array[2] == "Success") {
              trace("    |::* Connection was Accepted by the Server , continuing to
  load!");
              // SCRIPTS TO RUN WHEN THE CONNECTION HAS SUCCEEDED
              appInit();
              }

            if (infoMessage_array[2] == "Closed") {
              // SCRIPTS TO RUN WHEN THE CONNECTION HAS FAILED
              trace("    |::* Connection was Closed, returning the user!");
              appClose();
              }
            break;
</END EXERPT..>

NetConnection.prototype.onStatus = onStatusTemplate;
NetStream.prototype.onStatus = onStatusTemplate;

Note

If you are not comfortable using this generic onStatus handler, or if you would rather use your own onStatus handlers, you can use the following script in place of the #include "FlashComCustom.as" line:

onStatusTemplate = function (info) {
      trace("StatusChange: "+info.code);
      if (info.code == "NetConnection.Connect.Success") {
            appInit();
      } else if (info.code == "NetConnection.Connect.Closed") {
            appClose();
      }
};

NetConnection.prototype.onStatus = onStatusTemplate;
NetStream.prototype.onStatus = onStatusTemplate;

This script overwrites the onStatus prototypes for the NetConnection and the NetStream objects. Overwriting the prototype means that you never have to create an onStatus handler once this has been declared. Prototyping will be discussed in detail in Chapters 10, "STEP 10: Lobby Applications," and 12, "Client-Side (Flash) ActionScript."

The initial code is now complete. Now we'll look at the scripts specific to the subscriber and controller interfaces.

Step 2: Subscriber Scripts (Frame 10)

The Subscriber script controls the connection of the UI components to the NetConnection, and also establishes a receiving (subscription) NetStream from the server.

  1. Click keyframe 10 on the Actions layer to move your play head.

  2. Open the ActionScript panel (F9) in Expert mode (Ctrl+Shift+E). You should see an empty ActionScript Editor. If you do not, then you haven't created the keyframe (represented by a hollow circle in the Timeline). Click the frame, and press (F7) to create the keyframe. Ensure you have a keyframe on Frame 10.

  3. Set the global Speaker mode to false (for subscriber):

    // SET THE SPEAKER MODE FOR THE PRESENTATIONSWF COMPONENT
_global.speakerMode = false;

    This variable is monitored by the PresentationSWF UI component. When the variable is set to true, the PresentationSWF component enters into Presenter mode and allows the user to advance the presentation slides on all subscribers. When it is set to false, the component does not allow the user to advance the slides.

  4. Connect the UI components to the NetConnection:

    //
// CONNECT THE OTHER UI COMPONENTS TO THE NETCONNECTION OBJECT
peopleList_mc.connect(myConnection_nc);
presentation_mc.connect(myConnection_nc);
audioConf_mc.connect(myConnection_nc);

  5. Turn off the AudioConference UI component's visibility:

    audioConf_mc["_visible"] = false;
PeopleList_mc["_visible"] = false;

    This status will be toggled by the controller, similar to the ball you controlled in Exercise 9.1. The PeopleList component will also be hidden, because it is not used by the participants.

    Note

    You cannot connect a UI component to the NetConnection until it is available on the Flash stage. Users connected will not be shown unless the PeopleList component is active. Turning the visibility off lets the controller or speaker use the component, but the user cannot access it.

  6. Subscribe to the NetStream speakerStream. This will be a one-way stream originating from the controller movie. Attach it to the speaker_video object. If the controller has not connected, the stream will open and wait for a feed. Use the following code:

    //
// INSTANSIATE THE NETSTREAM OBJECT TO "speaker_ns"
speaker_ns = new NetStream(myConnection_nc);
speaker_video.attachVideo(speaker_ns);
speaker_ns.play("speakerStream");

  7. Create handlers in the NetStream variable that will respond to broadcast messages sent by anyone connected to the stream:

    //
// NETSTREAM MESSAGE HANDLERS
speaker_ns.audioConfControl = function(isAudioConfOK) {
      audioConf_mc._visible = isAudioConfOK;
};

speaker_ns.loadSWF = function(SWFtoLoad) {
      presentation_mc.loadSWF = SWFtoLoad;
};

    The only movie that has the broadcast script is the controller. audioConfControl toggles the visibility property of the AudioConference UI component. The loadSWF handler loads any presentations cued by the controller.

  8. Stop the play head from moving:

    stop();

That's the subscriber script. This script will not be executed until the play head enters Frame 10. It will retain all methods and connections described in Frame 1. Next, let's review the controller script.

Step 3: Controller Script (Frame 20)

The controller script is very similar to the subscriber script, in that it must connect the UI components. When the play head enters Frame 20, it will have missed the subscriber frame (10), and the connection method for the UI components will not have been called. You could optimize this code, but for this demonstration it is easier to present them separately. This script also connects the presenter's microphone and camera to the speakerStream.

  1. Set the global speaker mode to false, and connect the UI components:

    // SET THE SPEAKER MODE FOR THE PRESENTATIONSWF COMPONENT
_global.speakerMode = true;
//
// CONNECT THE OTHER UI COMPONENTS TO THE NETCONNECTION OBJECT
peopleList_mc.connect(myConnection_nc);
presentation_mc.connect(myConnection_nc);
audioConf_mc.connect(myConnection_nc);
audioConf_mc["_visible"] = false;

    The audioConference component must be connected, but will not be displayed to the speaker because the speaker stream is broadcasting the microphone. The speaker will be able to hear the audio conversation.

  2. Connect and start publishing the speakerStream sending the camera and microphone feeds to all subscribers:

    // CONNECT THE PUBLISHING SPEAKER STREAM
speaker_video.attachVideo(Camera.get());
speaker_ns = new NetStream(myConnection_nc);
speaker_ns.attachVideo(Camera.get());
speaker_ns.attachAudio(Microphone.get());
speaker_ns.publish("speakerStream");

  3. Set two functions that will be used by the enable audio PushButton:

    // AUDIO CONFERENCE MESSAGE BROADCAST FUNCTIONS
disableChat = function () {
      chatControl_pb.setLabel("Enable Audio Chat");
      chatControl_pb.setClickHandler("enableChat");
      speaker_ns.send("audioConfControl", false);
};

enableChat = function () {
      chatControl_pb.setLabel("Enable Audio Chat");
      chatControl_pb.setClickHandler("disableChat");
      speaker_ns.send("audioConfControl", true);
};

    This technique is exactly the same as the technique you used in Exercise 9.1. It toggles the visibility of the AudioConference UI component on each subscriber. It invokes the function, audioConfControl, that you scripted in the Subscriber interface.

  4. Stop the play head from moving forward:

    // playhead control
stop();

That's it! The interface and the Flash ActionScript is now complete. Save your movie, but don't test it yet. You still have to set up the main.asc script on the Flash Communication Server.

Step 4: main.asc Scripts

The server-side ActionScript is very simple. There are three operations required: loading the UI component framework, accepting the connection, and authenticating the user.

  1. Create a folder on the FlashCom Applications folder called chapter09.

  2. Locate the file simple_preso.swf in the Flash Communication Server samples folder named sample_broadcast.

  3. Copy the file into the chapter09 folder. This file contains the presentation that will be dynamically loaded by the PresentationSWF component.

  4. Create a new main.asc file in the chapter09 folder.

  5. To set up the Flash UI component framework, load the component.asc ActionScript Library:

    load("components.asc");

  6. Handle connection requests with application.onConnect, and accept all connections made to the application:

    application.onConnect = function(theClient) {
      // ACCEPT ALL CONNECTION REQUESTS
      application.acceptConnection(theClient);
};

  7. Create a new prototype method for the Client object to handle authentication and register the user with the UI component framework:

    //
// ADD A NEW PROTOTYPE METHOD (authenticateUser) TO THE CLIENT OBJECT
Client.prototype.authenticateUser = function(username) {
      trace("Called from Client");

      if (username == "Kevin") {
            clientRole = "controller";
      } else {
            clientRole = "subscriber";
      }
      trace("Role: "+clientRole);

      // SET THE USERNAME IN THE UI COMPONENT FRAMEWORK
      gFrameworkFC.getClientGlobals(this).username = username+"_"+clientRole;

      // SEND THE VALUE OF "CLIENTROLE" TO THE FLASH MOVIE
      return clientRole;
};

"What's this?" you might ask. This is the first time you have ever had to interact with the Object prototypes. Don't worry, you will be doing more of that in Chapter 10. This approach will allow all clients to invoke the authenticateUser method. The function will return an ActionScript object to the caller containing the decided role of the user.

Why do this here and not on the client? Authentication should, where practical, be processed on the server. This is to ensure that users cannot hack the SWF file and find the authentication string that will give them control of the application. It is also a good idea to perform this on the server, so you can change the authentication without worrying about users using the wrong version of the Flash movie.

The project is now complete and ready for testing.


Testing the Project

This is a complex project with a lot of moving parts that might fail. Testing and debugging applications might be daunting, but you should know where to look if something is not working. The list below is a checklist of things to consider if your application is not working as it should.

  • Ensure the Flash Communication Server is running and is accessible by your Flash movie.

  • Ensure the RTMP connection string is correct on the Actions layer at Frame 1.

  • Ensure you reload your application each time you make a change to the main.asc file.

  • Check the spelling in ActionScript and in the Properties window of each object. This is usually the source of many problems. Remember, SSAS is case sensitive. You should practice case-sensitive code in Flash MX ActionScript just to get into the habit.

  • If the play head isn't moving, ensure that you are responding properly to the Netconnection.onStatus code, NetConnection.Connect.Success.

  • Check the Client prototype in the main.asc file. You can test the syntax of the main.asc file by copying the entire source code into the ActionScript editor of a new Flash movie, and running the Code Checker on it. This will output any compile errors that might occur when the application instance is loaded. When you have fixed all errors, copy the script back into the main.asc file and reload your application.

  • If the server is rejecting your connection, ensure your main.asc file is created and is running the application.acceptConnection() method.

  • If components are not connecting, check spelling and check that you are connecting to the NetConnection.

  • If the movie plays without stopping, ensure you have stop() commands on Frames 1, 10, and 20 at the bottom of the ActionScript.

  • If the playhead won't move to the Controller frame, remember that the login is case sensitive. Check the value you are checking for on the server, and enter the exact name in the login box.

  • If the presentation is not loading, ensure the Flash (SWF) movie is being called from the correct location relative to the presetationApp.swf file. Ensure that the file exists and check spelling. The presentation will not load until the controller has logged in.

Troubleshooting can be the longest part of developing your projects, so heavy commenting and descriptive variable names will help you step through your project and isolate errors that might occur. Refer to the end of Chapters 11, "Server-Side ActionScript (SSAS)," and 12, "Client-Side (Flash) ActionScript," for additional troubleshooting tips for SSAS and Flash ActionScript.

When you are satisfied that your application is working as it should, remember to comment out or remove the line #include "NetDebug.as" from your ActionScript. This code will add undo size to the SWF file.


The Presentation File (simple_preso.swf)

The PresentationSWF UI component dynamically loads an external SWF movie. This external movie can be any normal Flash movie. The only consideration is that the PresentationSWF component will control the root Timeline of the loaded movie. The advance and reverse controller of the PresenationSWF component controls the position of the play head, stopping on each frame. The component will override any play head controls on the root Timeline.

The sample presentation used in this exercise is located in the sample applications installed with your Flash Communication Server. The FLA and SWF files can be found in the broadcast application.

This is not saying you can't have animation or sound within your movie. Animations, sounds, and interactivity can be encapsulated within MovieClips and placed on the Flash stage. The primary use for this will be presentations.

For those of you familiar with Microsoft PowerPoint, you can set up the Timeline to something that may be a little more familiar to you than the keyframe dots. The Timeline settings can be changed to display keyframes in Preview mode, similar to PowerPoint. Figure 9.9 shows how to access the Preview mode.

Figure 9.9. The presentation Flash file. Place the Timeline in Preview mode to simulate an interface similar to PowerPoint.

Presentation files must be accessible by both the controller and subscriber applications in order to be loaded.


Summary

Controller and subscriber applications demonstrate the power of the Flash Communication Server. Learning Flash design techniques will help you build applications that use the Timeline efficiently. Code and object reuse will help you build applications that can easily grow. Some of the concepts introduced in this chapter can be reviewed in Part II, "Implementing Flash Communication Server," of this book. Chapter 10 will introduce you to one more type of Flash Communication Server application, the Lobby application.


Chapter 10. STEP 10: Lobby Applications

This chapter will focus on building Macromedia Flash Communication Server MX Lobby applications. Lobby applications, like controller and subscriber applications, provide at least two interfaces for the user. The first interface is the lobby, which provides a space for all users to culminate. The room interface allows the same users to filter conversations and exchanges into a focused environment. This is achieved using multiple instances of an application.

Using multiple application instances with a simple Lobby application will complete your Flash Communication Server foundation. You will be introduced to the RoomList UI component in this chapter as a building block for building Lobby applications.


Lobby Application Overview

Lobby applications, like the Subscriber application introduced in Chapter 9, "STEP 9: Controller and Subscriber Applications," also maintain multiple user interfaces. The principle difference is that all user interfaces are public. A typical implementation is the chat room that contains multiple "rooms" for users to interact. You could also use instances to provide additional collaborative experiences such as multiple classrooms, meeting rooms, or other "creative" endeavors.

Network gaming is an excellent example to illustrate the concept. Let's say you build a game that can handle four players. A Lobby interface (shown in Figure 10.1) allows users to invite other users to join a game. Game play does not interact with other game plays concurrently running.

Figure 10.1. The Lobby interface.

Games are a great analogy because you would not want to code a game or set up an environment manually for each game being played. Lobby applications are the best way to illustrate application instances. You could have thousands of instances of the same application running concurrently, each maintaining unique data and streams. In the game example, each game independently maintains its own resources such as score, users, and game state. The application instance maintains unique SharedObject, Client, and Stream resources while sharing the same code base.

The RoomList UI Component

The RoomList UI component (shown in Figure 10.2) offers the basic functionality of a Lobby application. It also provides a great SharedObject model you can use as a foundation to extend the component.

Figure 10.2. RoomList Communication component.

Let's take a look at its basic features:

  • Create Room. This button invokes a dialog box for the user to enter a new room name and description. Behind the scenes, a new room "slot" is created in the SharedObject that manages the rooms. Each user connected to the application immediately sees the new room listed in the component's list box.

  • Join Room. When you have a room selected, the Join Room button highlights. This method connects the user to an instance of the room application. Its installed function interacts with JavaScript in an HTML browser to launch a new window and connect the room. This is a great technique, but we will overwrite this method to control the playhead within the same Flash movie.

  • Delete Room. This option is only available to the user who created the room, called the room owner. This is the only security provision of the component.

The RoomList component is the most complex in the Communication UI component set. The example provided in the manual is a must-read before you go too far with this chapter. The exercise in this chapter will take a different approach to implementing the RoomList UI component. It will involve extending the RoomList prototype with some new and different actions.

Extending the RoomList Component

Extending or overwriting the base functionality of the UI components is an important technique to master, if you plan to use any UI component as a starting point for your applications. This process is called overwriting an object's class (or prototype). You don't need to extend; however, it is required to apply additional features or to modify existing features. Overwriting is an advanced process and should be done only if you are comfortable with ActionScript and prototyping. There is no harm in practicing it. You will not modify the original source code; you will overwrite it from outside the component.

Let's take a quick look at overwriting an object's class. We'll change the operation of the MovieClip object's play() function. When you overwrite an object's method prototype, you change the operation across all instances of the object. For example, Phillip Kerman demonstrated this example in his book, ActionScripting in Flash MX (New Riders, 2002). Overwriting the MovieClip's play function:

MovieClip.prototype.play = function() {this.stop();}

There is no logical reason why you would want to do this, but it is a good illustration of how to overwrite an object's global prototype.

The first step with modifying any component is to assess what functionality you need it to do. For example, you might want to add a Click Handler to the PeopleList component, or add a log out feature for the SimpleConnect component. In the case of the RoomList component, you might want to add some internal security or change the data structure used in its SharedObject.

After your assessment, start by exploring the object's class library. Follow these simple steps to access any component's object prototype:

  1. Turn off the Enable Live Preview option (select Control, Enable Live Preview). The Live preview accesses an SWF movie embedded within the component to give you a display of the finished component during development. Jumping into the component without turning this off plays the SWF and may cause your Flash environment to become unstable. (The RoomList component consumes a lot of system resources when you open it up.)

  2. Drag the RoomList component to the Flash stage of a new movie.

  3. Open the Library panel (F11).

  4. Drill down into the Communication Components folder within the Library panel.

  5. Right-click (Ctrl-click for Mac) the RoomList symbol and select Edit (refer to Figure 10.3).

    Figure 10.3. Access the component's object prototype script by right-clicking the RoomList component in the Library.

  6. Locate the layer on the Timeline that contains the ActionScript (noted with a letter "a" above an empty keyframe. The RoomList uses the layer name Actions.

  7. Open the ActionScript Editor (F9) to reveal the Class file for the UI component.

Warning

DO NOT CHANGE ANY ACTIONSCRIPT HERE!

What you see is an ActionScript that describes the object's class (or prototype). A class is a collection of methods that can be assigned to instances. The methods available in an object are not available until you instantiate them. For example, you cannot access the .connect() method of a NetConnection object until you have instantiated it like this:

nc = new NetConnection();

If you are familiar with Java or JavaScript, this should be very familiar to you. Locate the method joinRoom. This method is used internally and is not exposed in the documentation, but you can still change it. When invoked, this function uses the getURL method to open a new web browser passing the username as a variable:

FCRoomListClass.prototype.joinRoom = function(){
      getURL(this.roomPath+"?appInstance="+this.rooms_lb.getSelectedItem()
      .data+"&username="+this.username, "_blank");
};

In the next exercise, you will overwrite this function to move the playhead using a gotoAndStop() function versus launch a new web browser using the getURL function. Don't modify this code; it should stay as is. You will overwrite it later in the exercise. When you are finished looking through the class, click Scene 1 below the Timeline layers to return to your main movie.


Chapter Exercises Overview

This exercise will step you through the process of developing a simple Lobby application to handle multiple chat rooms. Because this is the last introduction chapter, let's see how many UI components we can use—not because we have to, but because we can! This chapter will use relatively little ActionScript—just enough to keep it interesting.

The Flash UI components we'll use include the following:

RoomList

Chat

PeopleList

AVPresence

SimpleConnect

AudioConference

ConnectionLight

UserColor

Bandwidth

Figure 10.4. The Login interface.

Figure 10.5. The Lobby interface.

Figure 10.6. The Chat Room interface.

Just because a large gamut of UI components will be used, you should still build a "use case" scenario to help you when you are coding.

The user opens the Flash movie and is presented with a Login screen containing a Login prompt. There is no password authentication with this application. Everyone has access.

Flash Communication Server accepts all connection requests and signals the client to enter the Lobby screen. The Lobby contains a list of current rooms and an option for the user to create a new room.

Joining a room enters the user into the application instance of the selected room. The user can join a chat using text messaging or capture one of three video windows. Users who do not have video can participate using the Audio chat (audioConference) tool.

At any point, the user can exit the chat room to return to the lobby and connect or create another room.

If the user shuts down his browser, or disconnects during the visit to the room, the application cleans up all records of the user automatically.

Exercise 10.1: The Macromedia Flash MX Interface

As you did in Chapter 9, let's start by building the Flash user interface and then move on to the scripts. The artwork used in these examples is available on the web site for this book (http://flashcom.PangaeaNewMedia.ca/).

Start by preparing the Timeline. Use Figure 10.7 as a reference as you construct it.

Figure 10.7. The Chat Room interface.

  1. Create a new document in Flash MX.

  2. Create six new layers with the following names: Labels, Actions, Login, ConnectionLight, TextPrompts, and UIComponents.

  3. Click Frame 30 on the Labels layer and drag across all layers to highlight them. Insert 30 frames across all layers (F5 or select Insert, Frame).

  4. Create keyframes on all layers on Frames 10 and 20. You can use the same technique highlighting multiple frames. When they are highlighted, press F7 (select Insert, Keyframes).

  5. Remove the keyframe at Frame 20 on the Login layer. Click the keyframe and press Shift+F6.

That's it for the Timeline. Now, assemble the interface components on the Flash stage. Remember to always know where your Timeline cursor is. This is a common mistake when developing in Flash.

The Login Interface (Frame 1)

The login interface is exactly the same as it was in Chapter 9. Use Figure 10.8 as your layout guide. Follow these steps:

  1. Place your Timeline cursor at Frame 1 on the Login layer. Place the following elements on the Flash stage with this frame selected:

    • Text Input box with the instance name login_txt.

    • PushButton #1 (from the standard Flash Communication Server UI components) with the following properties set in the Properties window:

      Label: "Login"
ClickHandler: "app_Login"

  2. Place your Timeline cursor at Frame 10 on the ConnectionLight layer. Place the following elements on the Flash stage with this frame selected:

    • PushButton #2 (from the standard Flash UI components) with the following properties set in the Properties window:

      Label: "Logout"
ClickHandler: "app_Close"

    • ConnectionLight #1 from the Flash Communication UI components with the instance name connectionLight_mc.

    • ConnectionLight #2 from the Flash Communication UI components with the instance name connectionLight_rooms_mc.
Figure 10.8. The Login interface guide.

The ConnectionLights and Logout button will be available across all interfaces except the login, so there is no blank keyframe required on Frame 20. There are two ConnectionLights, so you can monitor two NetConnections (explained later in Exercise 10.2). Place a small text label next to the lights, as shown in Figure 10.8.

The Lobby Interface (Frame 10)

The Lobby interface is very simple. Use Figure 10.9 as your guide for layout. It only contains the RoomList UI component and a couple text prompts. Follow these steps:

  1. Click on Frame 10 on the UIComponents layer.

  2. Drag a RoomList UI component from the Communication UI Components panel.

  3. Assign it the instance name of roomsList_mc.

  4. If you want, add some text prompts to Frame 10 on the TextPrompts layer. We won't be using the Room Application Path parameter for this exercise, so just leave it blank.
Figure 10.9. The Lobby interface guide.

Add some color to the background to make it friendly for your user, and you are off to the races (see Figure 10.10)!

Figure 10.10. The Lobby interface with a background applied.

The Chat Room Interface (Frame 20)

The Chat Room interface is an assembly of UI components. Really, to demonstrate this tool, all you need is the Chat tool; but because this is the finale, let's have some fun. Each component will exist on the same layer on Frame 20. Use Figure 10.11 to help you build the interface:

  1. Click Frame 20 on the UI Components layer and add the following UI components with their properties as noted:

    Chat: Audio Conference:

    Name: chat_mc

    Width: 228

    Height: 360

    X: 25

    Y: 15

    Name: audioConf_mc

    Width: 100

    Height: 100

    X: 422

    Y: 180
    PeopleList: peopleList_mc
    Chat Color: AVPresence:

    Name: userColor_mc

    Width: 100

    Height: 15

    X: 152

    Y: 380

    #1 Name: av1_mc;

    Presenter SharedObject: av1

    #2 Name: av2_mc;

    Presenter SharedObject: av2

    #3 Name: av3_mc;

    Presenter SharedObject: av2
    Bandwidth:

    Name: bandwidth_mc

    Width: 100

    Height: 17

    X: 400

    Y: 350

  2. Add some text prompts (as noted in Figure 10.12) at Frame 20 on the Text Prompts layer for your users. Name the text objects: roomname_txt, description_txt, id_txt, username_txt, and roomname2_txt.

    Figure 10.12. The Room interface with a background applied.
Figure 10.11. The Chat Room interface guide.

That's it for the interface. Add some color to the interface to liven it up and you're ready for coding! The next exercise will add the code.

Exercise 10.2: Coding the Application

The ActionScript for this project is straightforward. Because this application uses a lot of UI components, there is very little scripting required. All processes are encapsulated within a series of functions to make it easier to present. Certain methods may not be the most efficient because they are built with training in mind.

The concept behind a Lobby application is switching between application instances. You can maintain multiple NetConnection objects within a single Flash client; you can even be connected to any number of servers at the same time. Maintaining more than one connection exposes the Flash client to resources such as streams or SharedObjects across multiple application instances or servers.

This may not be your best option, especially if user licensing is an issue. Each connection made to the server is registered as a licensed seat. If each Flash client maintains two connections with the server, you have just cut the number of clients that can connect in half. A 10-user license server (Personal edition) supports only five users if each Flash client requires two connections.

Lobby applications must carefully manage their network connections to ensure there are not unnecessary connections being sustained. The ActionScript for this project handles the switching of the application instance connections between the Lobby instance and the rooms instance.

This project, as you already know, takes a much different approach to designing a chat room than is presented in the manual. The underlying difference is that this application is completely integrated within a single movie and application. The manual's application relies on HTML, two separate movies, and two separate applications. Your first job in ActionScript is to reprogram the join method of the RoomList component to not launch a separate browser window.

Initialization (Frame 1)

If you explore the RoomList component's class, you would come across the prototype method, joinRoom();. This method is called internally by the UI component when the Join Room button is clicked on the interface. When called, the prototype method uses getURL() to open a new web browser sending data through the URL scope to JavaScript handlers embedded within the HTML file. We don't want the web browser to be involved. When the user clicks the Join Room button, we want to have the method call a custom function outside the prototype so the processes can be changed easily. When selected, the details about the room are transferred from the SharedObject to a _global structure inside the Flash movie. This lets us access data that will become unavailable when the Lobby connection is closed. Reprogramming the prototype is your first job. Here's what to do:

  1. Open the ActionScript Editor (F9) in Expert mode (Ctrl+Shift+E).

  2. Click Frame 1 on the Actions layer in the Timeline.

  3. Reprogram the joinList prototype. Place the following code as the first script in the editor:

    /* FRAME 1: "LOGIN" */
// **REPROGRAM THE JOINROOM PROTOTYPE IN THE ROOMLIST CLASS
FCRoomListClass.prototype.joinRoom = function() {
      var selectedRoom = this.rooms_lb.getSelectedItem().data;
      // transfer the room data to a local _global variable
      _global.activeRoom = this.so.data[selectedRoom];
      // increment the user count
      this.so.data[selectedRoom].users++;
      // invoke a local function, "loginToRoom()"
      loginToRoom();
};

    This method retrieves the selected room index from the component's listbox. It then transfers the selected room object stored in the remote SharedObject to the global structure, activeRoom (see Figure 10.13 for a look at what is stored within the activeRoom object). It increments the users accessing the room, and then calls the function loginToRoom that will be developed a little bit later.

    Figure 10.13. The Debugger displays the structure of the activeRoom global variable.

  4. Create a generic onStatus handler to trace the Information object codes; then, overwrite the prototypes for NetConnection, NetStream, and SharedObject:

    // **REPROGRAM THE ONSTATUS EVENT PROTOTYPES
onStatusTemplate = function (info) {
      trace("StatusChange: "+info.code);
};
NetConnection.prototype.onStatus = onStatusTemplate;
NetStream.prototype.onStatus = onStatusTemplate;
SharedObject.prototype.onStatus = onStatusTemplate;

  5. Set up two global variables: session is used to store information about the user during the session and FlashComURI is used to define the location of the Flash Communication Server. Because you will be doing a lot of switching between connections, it is helpful to assign the URI to a global variable. Figure 10.13 shows the session and Flash Communication Server objects in use:

    // **INITIALIZE THE CLIENT
_global.session = new object();
_global.FlashComURI = "rtmp://192.168.0.1/chapter10/";

  6. Create two instances of the NetConnection: one for the lobby and one for the rooms. You could use a single NetConnection object, but for illustration purposes, it is useful to have them as separate instances. Note, you do not connect these objects until the user logs in or selects a room:

    // Define the Lobby and Room NetConnections
lobby_nc = new NetConnection();
room_nc = new NetConnection();

  7. Attach the two connection lights to the relative NetConnection objects:

    // Attach the Connection Lights
connectionLight_mc.connect(lobby_nc);
connectionLight_room_mc.connect(room_nc);

  8. Create the app_Login function used by the Login button to connect the server to the lobby_nc NetConnection. This function moves the playhead to the Lobby interface, where the function loginToLobby() is called:

    // **LOCAL APPLICATION FUNCTION HANDLERS
app_Login = function () {
      // Login Button was clicked, make the connection with the server
      _global.session.username= login_txt.text;
      lobby_nc.connect(FlashComURI+"chatLobby", session.username);
      gotoAndPlay("Lobby");
};

  9. Create the app_close function used by the Logout button to close the lobby_nc connection and move the playhead to the Login interface (Frame 1):

    // ** APP_CLOSE
app_close = function () {
      trace("function: app_close");
      lobby_nc.close();
root.gotoAndStop("Login");
};

  10. Create a function used by the Logout button to close the room and return to the Lobby interface:

    // ** ROOM LOGOUT
room_logout = function () {
      if (room_nc.isConnected) {
            room_nc.close();
      }
      _root.gotoAndPlay("Lobby");
};

  11. Create the loginToLobby function called by Frame 10, the Lobby interface. Because this function is run each time the playhead enters Frame 20 (or the Lobby interface is displayed), the first process is to determine if the lobby_nc connection is currently active. If it isn't, a connect command re-establishes the connection using the session.username value as the login. The RoomList must be connected.

    After the roomsList_mc is (re)connected, you have access to its remote SharedObject. If the user is returning to the lobby from a room, the _global.activeRoom object will contain the room data. Test the object, read the room information, and decrement the users value of the corresponding slot in the SharedObject. When finished, clear the _global structure.

  12. Finally, program the Logout button defining the Click Handler and the label:

    // **SETUP THE LOBBY
//  (this function MUST be run by frame 10, with the RoomList on the stage!)
loginToLobby = function () {
      // reconnect to the Lobby instance if returning from a room
      if (!lobby_nc.isConnected) {
             lobby_nc.connect(FlashComURI+"chatLobby", session.username);
             trace("logged back into the Lobby");
      }
      // Connect the RoomList
      roomslist_mc.connect(lobby_nc);
      // decrement the Total users in the room, if the user was connected
      if (activeRoom != undefined) {
             roomsList_mc.so.data[activeRoom.id].users—;
            _global.activeRoom = undefined;
      }
      // Reset the Logout Button
      logout_pb.setClickHandler("app_close");
      logout_pb.setLabel("Logout");
};

  13. Create a handler that sets up the room selected by the user. When called, this function closes the Lobby connection and establishes the room connection using the _global.activeRoom object to acquire the instance name (ID) used in the connection string. Again, the session.username value is used to identify the user to the new instance.

    Next, reprogram the Logout button defining a new Click Handler and label, and then move the playhead to the Room interface:

    // **LOG INTO ROOM
loginToRoom = function () {
      // close the connection to the Lobby Instance
      lobby_nc.close();
      // AUTO-CONNECT TO THE ROOM INSTANCE, USING THE GLOBAL ALREADY DEFINED
      room_nc.connect(FlashComURI+activeRoom.id, session.username);
      // REPROGRAM THE LOGOUT BUTTON
      logout_pb.setClickHandler("room_logout");
      logout_pb.setLabel("<< Lobby");
      // PLAYHEAD CONTROL
      _root.gotoAndStop("Room");
};

  14. Finally, ensure the playhead doesn't move until it's told to move. Insert a stop();command:

    // CONTROL THE PLAYHEAD
stop();
Lobby (Frame 10)

You have already programmed the script for the Lobby interface in Frame 1. The only script in this frame is the call back to the loginToLobby(); function and a playhead stop(); command:

/* FRAME 10: "LOBBY" */
loginToLobby();
stop();
Room (Frame 20)

Here is where you will really notice the convenience of using the Flash UI components. The script in this frame does nothing more than connect the UI components and assign the room information to the text objects on the screen. The only thing you need to remember is that the AVComponents need to run the function to assign the username to them before they are operable:

/* FRAME 20: "ROOM" */
//
// Connect the UI Components to the new connection
chat_mc.connect(room_nc);
color_mc.connect(room_nc);
peopleList_mc.connect(room_nc);
bandwidth_mc.connect(room_nc);
audioConf_mc.connect(room_nc);

//
// Connect the AVPresence Components
av1_mc.connect(room_nc);
av2_mc.connect(room_nc);
av3_mc.connect(room_nc);
av1_mc.setUsername(session.username);
av2_mc.setUsername(session.username);
av3_mc.setUsername(session.username);

//
// Set the Screen Text Data
username_txt.text = session.username;
roomName_txt.text = activeRoom.room;
description_txt.text = activeRoom.description;
owner_txt.text = activeRoom.id;

//
// **CONTROL THE PLAYHEAD
stop();
Sever-Side ActionScript (main.asc)

Create a folder called chapter 10 in the Flash Communication Server's application folder.

There really is no processing done by the server for this application beyond the normal accepting the connection request and setting the username to the UI component framework. Add the following script to a new main.asc file and save it in the chapter 10 folder:

/* CHAPTER 10: LOBBY CHAT ROOM */

load("components.asc");
application.onConnect = function(newClient, newUserName) {
      gFrameworkFC.getClientGlobals(newClient).username = newUserName;
      application.acceptConnection(newClient);
};

That's all there is to it! This project gives you the foundation for building great Lobby applications using the Flash Communication Server UI components. It has also paved the way for you to start exploring ways to extend the UI components' native functionality. Be sure to check out the book's web site (http://flashcom.PangaeaNewMedia.ca/) for a live example of the Chat room and the source code!


Summary

So that's the end of the 10-step introduction to Flash Communication Server MX. Have you figured out the Tin Can reference yet? At this point, you have enough information to really do some damage (just kidding). You have been introduced to the Flash Communication Server UI components, and almost every ActionScript object available to you in the Flash Communication Server, from a very top-level perspective. The next part will take a more detailed look at the server-side ActionScript model and then move on to a detailed overview of the new Flash elements. Flash Remoting MX and database access are covered in Chapter 14, "Server Administration."

The appendices included in this book are a great reference tool for all the Flash Communication Server objects, both on the server and the client. The Flash UI components are also presented in detail.

Please visit this book's Flash Communication Server MX web site for updates and all the source code for the examples in this book at http://flashcom.PangaeaNewMedia.ca/.


Part II: Implementing Macromedia Flash Communication Server

11 Server-Side ActionScript (SSAS)

12 Client-Side (Flash) ActionScript

13 Accessing External Data

14 Server Administration

15 Communication Application Architecture Strategies


Chapter 11. Server-Side ActionScript (SSAS)

Server-side ActionScript (SSAS) is just like Macromedia Flash ActionScript except it exists on the server. Just as Flash ActionScript is based on the ECMAScript-262 specification, SSAS also uses the standard as a foundation. SSAS closely follows the implementation of Server-Side JavaScript 1.5 (SSJS) used by the SunONE Server and the Netscape Enterprise Server. You will find it interesting to review more about SSJS presented in Netscape's Developer pages (http://developer.netscape.com). SSAS does not include the SSJS LiveWire objects used for direct database access, nor does it include the object to connect to email server and the file system. This was done to ensure SSAS's security model was tight. SSAS cannot access the file system or database server directly. SSAS can handle databases and external servers through Flash Remoting MX and compatible application servers. Flash Remoting MX will be discussed in detail in Chapter 13, "Accessing External Data."

SSAS cannot directly control Flash elements such as MovieClips, buttons, or objects with this script. However, it can invoke methods within the Flash movie that can alter the elements of the movie. SSAS acts like a facilitator between multiple Flash movies and other servers. SSAS is the communication hub. You can build objects to store data, or methods to handle communication events.

There are two important things you should remember before you start working with SSAS:

  • Any change made to SSAS in ASC files requires a reload of the application.

  • SSAS is CaSe seNSitiVe, unlike its Flash MX counterpart. For example, the following two variable definitions would create two different variables:

    var myVariable = 123;
var MYVARIABLE = 456;

This chapter will step you through the objects available to you with SSAS including SharedObject, Stream, Application, Client, and NetConnection. You will review some SSAS that you can use for a simple authentication system using an ActionScript array. The chapter will also handle techniques you can use to help debug SSAS. Each object's methods, properties, events, and information objects are presented in the Quick Reference appendices in the back of this book.


The main.asc File

The main.asc file is the heart of your application. You have used it already in previous chapters as a place for server-side ActionScript. Macromedia Flash Communication Server always looks for the main.asc file when it is loaded the first time. If the main.asc file is not available, Flash Communication Server looks for a file with the name of the application. For example, Communication Server would look for a file called myApp.asc within an application called myApp. main.asc is always loaded first, if it exists. All SSAS must stem from either of these files. The server looks first for main.asc, and then it looks for myApp.asc. If both files exist, main.asc takes priority, and myApp.asc is ignored. This does not mean that all SSAS must exist solely in the file. You can "include" external scripts inline. You saw this in earlier exercises when the components.asc file was loaded. This particular load reference includes the server-side counterparts for the Flash UI components that are nothing more than SSAS object classes.

The process of including scripts is handled by the load method. This method loads any ASC files relatively located to the main.asc or application-named file. Loaded scripts are inserted inline just like server-side includes, or a <CFINCLUDE> for those Macromedia ColdFusion buffs out there. They are compiled after being loaded with scripts inside the main.asc file. Their libraries are made available to the Application instances.

SSAS is compiled into the application each time it is instantiated. When a change is made to server-side files (ASC files), those changes do not take effect in an Application instance until it is reloaded. This can get tricky if you have multiple instances running. It is possible to have multiple versions of the application running, if you do not reload each instance. There are three ways to reload your application: through the Communication App Inspector, the Administration Console, or by using the ActionScript API.


Application Instances

Like any normal ActionScript object, applications have to be instanced before they can be used. This is an important concept when using the Flash Communication Server. In Chapter 10, "STEP 10: Lobby Applications," you saw instancing in action, with the RoomList component. SSAS within the main.asc file is compiled each time a new instance of the application is run. You create instances using the NetConnection.connect ActionScript in either the Flash player or SSAS. As you saw earlier, you can also manually create an instance using the App Inspector. Each Application instance operates within its own context. Users connected to instances of an application cannot access other instances without closing the current connection and opening another connection (see Figure 11.1). This is an extremely important security feature with the Flash Communication Server.

Figure 11.1. The Application instance makes a copy of the Application object. Instances have no relationship with each other without a NetConnection bridge.

Applications have a scope that can be used by all clients connected to a single Application instance. The application scope does not include other instances. Methods, properties, and events can be created to handle when an instance starts and when users can connect. You saw this when the Application.onConnect event was created to handle a Flash player connecting.

The Application instance is defined as a collection of stream objects, SharedObjects, and (connected Flash) clients. Each application and instance must have a unique name that must adhere to the Uniform Resource Identifier (URI) convention.


Components and the ScriptLib Folder

The ScriptLib folder contains libraries that extend the native Flash Communication Server objects. This folder is installed outside the Applications folder on your server because it can be shared between all applications, adaptors, and virtual hosts. These will be presented later in Chapter 14, "Server Administration."

Two groups of libraries are shipped with the Flash Communication Server. The Components library includes the required server-side logic for the Flash UI components. This library must be loaded before you can use the components. The second library is the NetServices library, which is required if you plan to connect with external application servers using Flash Remoting MX. The library contains two primary classes. NetServices handles Flash Remoting MX connections, and RecordSet is an advanced object that operates as a standard database query object. Flash Remoting is presented in detail in Chapter 13, "Accessing External Data."

In every exercise you have done, the file components.asc was loaded into main.asc. This file is a controller file that loads a collection of classes required by the Flash UI components. Each UI component has a class defining the server-side methods, properties, and events. These files exist inside the ScriptLib/components folder. You can alter these files; however, it is not recommended. If you must modify methods, copy the prototype function from the component class file and overwrite it in your main.asc file. Doing this ensures that you do not corrupt the component class or affect any other applications on the server. If you change anything within the ScriptLib folder, you run the risk of corrupting not only the component for this instance, but for every application running within that virtual host.

The ScriptLib folder is where the server looks for files that are not found in your application folder. You can change the location of this folder by modifying the Application.xml file within the folder:

[%FlashCom installPath%]/conf/_defaultRoot_/_defaultVhost_/

Look for the following entry:

<ScriptLibPath>c:\inetpub\wwwroot\flashcom\scriptlib</ScriptLibPath>

You can add more ScriptLibPaths to the Application.xml file by separating them with a semicolon (;). The server looks for files first in your application folder, and then from left to right in this ScriptLibPath list. You can also place files within the ScriptLibPath that you want accessible by all applications. For security reasons, be careful what you place in here—you wouldn't want other applications accessing custom classes they shouldn't.


Server-Side Objects

SSAS has many of the same communication object models that you have become familiar with in Flash—NetConnection, Stream (also known as NetStream), and SharedObject—with two additional objects—Application and Client. Flash ActionScript uses these objects to connect, stream, and share data with the server. The server can also use the objects to connect, stream, and share data with other Flash Communication Servers or application servers connected to databases. Flash Communication Server ships with two additional libraries—Components (components.asc) and NetServices (netservices.asc)—that add a number of other objects to SSAS. When loaded, these extra objects become available to handle the Flash UI components and Flash Remoting MX. Let's review each object individually.

NetConnection (SSAS) Object

There exists no relationship between the server-side NetConnection object and the client-side NetConnection object. A client connection with a Communication Server accesses the Application object to handle connection events. NetConnection (on the server) is used to connect to servers. These servers can include other Application instances on a local server or an Application instance on a remote server.

Much like the client-side NetConnection, this object has all the same methods, properties, and events. These features allow you to connect and call methods on other communication or application servers and handle any status changes just like a Flash client would. In essence, when you use the NetConnection on the server, your server becomes a client.

Connecting with other Application instances on the same Flash Communication Server or servers that are remote is just as simple as connecting the Flash player with the server. When you use NetConnection, the receiving server (or Application instance) handles the server as another client, using the events in the Application object on the called server.

Exercise 11.1: Calling an Application Instance from SSAS

This exercise will have your Flash movie call the instance myInstanceName from the SSASTests application. A value will be passed invoking the server to call another instance of the same application using the NetConnection object in SSAS.

The exercise will show how you can connect to another Application instance from SSAS, but the same technique can also be used to connect with a remote Flash Communication Server:

  1. Create a new folder called SSASTests in the FlashCom applications folder.

  2. Open a new file in Flash MX.

  3. Open the ActionScript panel (F9).

  4. Enter the following script on Layer 1, Frame 1:

    nc = new NetConnection();
nc.onStatus = function(info) {
      trace("LEVEL: "+info.level+"  CODE: "+info.code);};
nc.connect("rtmp:/SSASTests/myInstance", "kevin", "bird");

  5. Save your Flash movie.

When the username "kevin" is passed through the .connect method, it triggers the server to connect again to a different instance name, myServerInstance. This time, a different username is used so the server won't enter into an infinite loop. If you pass the same username, the server will continue to connect to itself and you will probably bring down the server. (This is said out of experience.)

Follow these steps to create the SSAS connection when the username, "kevin," is received:

  1. Create the main.asc file in the SSASTests folder.

  2. Add the following script to main.asc:

    application.onConnect = function(clientObject, username) {
      // ** ACCEPT THE CONNECTION **
      application.acceptConnection(clientObject);
      // ** CONNECT TO A NEW INSTANCE IF USERNAME == "kevin"
      if (username == "kevin") {
            trace("the Server is connecting");
            nc = new NetConnection();
            nc.onStatus = function(info) {
                  trace("LEVEL: "+info.level+"  CODE: "+info.code);
                  if (info.code == "NetConnection.Connect.Success") {
                        trace("you Connected - Great! Go get your self something nice");
                  }
            };
            nc.connect("rtmp:/SSASTests/myServerInstance", "notKevin");
      } else {
            trace("the Server is NOT connecting");
      }
};

  3. Save the main.asc file.

As you can see, there is an IF statement embedded within the .onConnect event that monitors the username value for "kevin." If the value matches, a new NetConnection is invoked with a trace informing you that it is connecting. Follow these steps to test your application:

  1. In Flash MX, open the Communication App Inspector (in the Window menu).

  2. Test your movie (Ctrl+Enter).

When these scripts are tested with Flash MX, a review of the App Inspector will show two instances of the same application running (see Figure 11.2).

Figure 11.2. The App Inspector displays the Application instances that are active on the server.

Now, monitor the trace activity as it happens in the Live Log:

  1. Close your test movie in Flash MX. (Leave the FLA file open; you will be testing it again.)

  2. Select the myInstance instance in the App Inspector and click View Detail. Because myInstance is acting as a client, trace actions are output to its Live Log.

  3. Test your Flash movie (Ctrl+Enter) again while monitoring the Live Log window.

You will see the trace information including the onStatus trace in the Live Log window. Figure 11.3 demonstrates the output created by this application's instance. If you do the same with the other instance, you will not see the onStatus output, because a NetConnection is not being established from that instance.

Figure 11.3. Watch your application's trace activity in the Live Log window. You must first have an instance running before you can access this window. Use the Reload App button to watch traces when the application loads.

Although this may seem an impractical exercise, it demonstrates the ease of connecting with another server. Where the IP address (192.168.0.1) is mentioned, replace that with a proper URI of a remote Flash Communication Server.

Application Object

The Application object contains methods, properties, and events that give you control over a connection invoked by a Flash client and also provides information about the Application instance. Application instances, as you read earlier in this chapter, are loaded when called by a client or through the App Inspector. Each method, property, and event is specific only to the instance, and has no relationship to other instances running on the server.

The Application class is one that you will use most often. Application events handle NetConnection commands from a Flash client or another connected Flash Communication Server. The Application methods offer control over the maintenance of your application, such as cleaning up SharedObjects or streams that weren't closed properly. There are also methods to manage class registration or proxy a remote NetConnection.

When the NetConnection.connect method is called by a Flash client or another server, there are two events that could be triggered. If the Application instance hasn't been loaded, the event Application.onAppStart is called before any other function. After the instance is loaded, every client connecting triggers the Application.onConnect method. This is a function primarily used to assemble any authentication scripts or prepare unique objects, such as streams or SharedObjects. The most important aspect of the onConnect is to accept or reject a connection request. Like all ActionScript events, you are required to overwrite both the onAppStart and onConnect events.

You can create any additional properties or methods within the application scope. These methods and properties are available to each client that connects to manage the details of the Application instance.

Exercise 11.2: Authenticating a User

A common use of the onConnect method is accepting or rejecting a connection. You have seen this event at work in earlier chapters when you scripted a connection to the Communication Server. This exercise will manually populate an array of usernames and passwords when the application starts. Flash Communication Server uses this array to challenge a login and password sent from the Flash player and decides to accept or reject the connection. To authenticate a user, follow these steps:

  1. Create a new folder in the Flashcom Applications folder called mySecureApp.

  2. Create an empty main.asc file within the mySecureApp folder.

  3. Add the following script to the main.asc file:

    application.onAppStart = function() {
      // define the array of users that will be authenticated to use this application
      user_array = [];
      user_array.push({uname:"kevin", password:"bird"});
      user_array.push({uname:"colin", password:"tank"});
      user_array.push({uname:"sharon", password:"craft"});
      user_array.push({uname:"sandy", password:"car"});
};

You have just overwritten the onAppStart method for this application. This script runs only once when the application is instantiated. For those of you who might be wondering, "This is a strange way to declare an array," this array is known as an associative array or an array of objects. You might also notice that instead of using new Array when declaring the array, a double square bracket is used to declare an empty array ([]). The array of objects operates very similar to a database record set, which is a little foreshadowing to Chapter 13. This associative array is used as a data store by the onConnect method to ensure each person accessing the application has a valid login and password.

For a Flash client to connect to the application, the connection must be "accepted." You can accept connections using the methods Application.acceptConnection or Application.rejectConnection. Combining these methods with the onConnect event is the most common use.

The NetConnection call from a Flash client sends the login and password as custom parameters of the .connect method. They are handled by the onConnect method. You use those values to match against the data in the array. These next steps will construct the authentication script inside the onConnect handler:

  1. Below the onAppStart function, add the following script to overwrite the onConnect method:

    application.onConnect= function(clientObject, username, password) {
      // Loop through the array to challenge the username and password passed
      through the connect

  2. Declare a variable called isAuthenticated to false. You use this to store a successful match in the array loop:

    var isAuthenticated = false;

  3. Create an array loop that steps through the array trying to match the username and password combination. If the challenge is true, isAuthenticated will be true, and the loop will break out:

          for (uname in user_array) {
            trace("testing" + uname);
            var thisUSR = user_array[uname].uname;
            var thisPWD = user_array[uname].password;
            var challenge = (username == thisUSR) && (password == thisPWD);
            if (challenge) {
                  var isAuthenticated = true;
                  break;
            }
      }

  4. When the loop has finished, a second challenge of the isAuthenticated variable accepts or rejects the connection. This is the end of the onConnect function, so make sure the closing bracket is included:

          // Accept/Reject the Connection
      if (isAuthenticated) {
            application.acceptConnection(clientObject);
      } else {
            application.rejectConnection(clientObject);
      }
};

This may look a little complicated, but it really isn't. You can immediately see that this method is set up to receive three parameters:

  • clientObject

  • username

  • password

You can have as many parameters in this method as you need; however, you must always pass the clientObject to assign this client to the application. The bulk of the work is done by the looping through the array of objects. The username and password are transferred into temporary variables on each loop. A challenge looks for a matching username/password combination. Each loop sets the challenge variable to false until a correct match is found. The loop breaks out with a correct match, setting the isAuthenticated variable to true. After the loop, the isAuthenticated variable is challenged, and if it is true, the application accepts the connection. This changes the status of the connection and triggers the NetConnection.onStatus function on the Flash client (not shown here).

The Flash player does not have an interface for this exercise. Instead, you hardcode the username and password values. The values are passed to the.connect method as extra parameters. Let's script the call that the Flash player will make:

  1. Open a new Flash movie within Flash MX.

  2. Add the following script to Layer 1, Frame 1:

    nc = new NetConnection();
nc.onStatus = function(info) {trace("LEVEL: "+info.level+"  CODE: "+info.code);};
nc.connect("rtmp:/mySecureApp/myInstance", "kevin", "bird");

  3. Save the Flash movie.

This script makes a connection call to the myInstance instance of the mySecureApp application. Because there is no Flash interface used in this exercise, you must monitor the trace activity of both the Flash movie and the server. You need the App Inspector window and the Flash MX output window. Follow these steps to manually load the application in the App Inspector:

  1. Open the App Inspector window in Flash MX.

  2. Load the instance manually using the App/Inst text input box on the main screen of the App Inspector. Enter mySecureApp/myInstance in the field, and click Load.

  3. Click the new active instance and select View Detail.

  4. Click the Reload App button to monitor the trace actions while the Application instance reloads.

  5. Test your Flash movie (Ctrl+Enter).

If everything is correct, your Flash MX output window should display a connect.success status message. Now, try a wrong username and password and test again to receive the connect.rejected status message.

The Application object also has application.onDisconnect and application.onAppStop events. When a user closes the browser, or disconnects the application, the onDisconnect method is triggered. When the server shuts down, or the instance is reloaded, the onAppStop method triggers. Try these out by placing the following functions at the bottom of your main.asc file, and then reload your application:

application.onDisconnect = function() { trace("Was it something I said?"); }
application.onAppStop = function() { trace("Thanks for all the Fish!"); }

If you know you will have multiple instances running within a single application, you could use the application.name property as a challenge to grant additional privileges to the user. The best place for this test is within the onConnect event:

application.onConnect = function(myClientObj) {
    if (application.name == "SSASTests/underwear"){ trace("welcome to the underworld!"); }
}

To get the most out of what the Application object can offer, review the Quick Reference guides in the appendices.

Client Object

By now, you have a good understanding of object-oriented programming (OOP) concepts. A key to understanding OOP is realizing that objects can be instanced (or instantiated). The concept of a prototype can be daunting at first; however, it is very straightforward. Each of the objects you have reviewed so far are prototypes. A prototype is like a stencil. In OOP, you prototype methods, properties, and events. Each object used is actually a prototype.

How does this relate to the Client object? Macromedia has taken the concept of OOP and related it to everything, as you saw with the Application object. When a client (Flash player) successfully connects to an Application instance, that client becomes an instance of the Client object on the server. The properties, methods, and events that are built into the Client class are instanced and now only relate to that Client instance. There is no connection to other instances. A quick example of this is the property Client.ip. This property exposes the IP address of the connected client to the server.

This IP address is unique for each client that is connected to the Flash Communication Server. Similar properties are available to return the Flash player version and operating system for each client.

The Client prototype (or class or object) can be used to set permissions to access streams or SharedObjects, or set the limits on bandwidth.

Creating Custom Client Methods and Properties

You can create custom methods and properties within the Client instance. When you do this, the Flash client can access server-side methods and properties. Using the NetConnection.call method in Flash MX, you can invoke methods that have been defined in that Client's instance. There are some tricks to this, however. First, you can only create Client methods and properties after the client's connection has been accepted, using the Application.acceptConnection. This is because there has been no instance of the client until it has connected. After the connection has been accepted, you can then set new functions that can be called by the Flash client. The following example shows a custom function, called hello, that can be accessed by the client after the connection has been accepted:

ClientObj.hello = function(name){
return "hello from the server, "+ name;
}

This function must be declared after the connection has been accepted. To access this function in Flash, use the NetConnection.call method. This function takes one parameter.

nc.call("hello", new eventHandler, "Kevin Towes");

Remember that this function is not available until the server has accepted the connection and created the Client object. To test this, place the client-side code within a nc.onStatus handler.

Exercise 11.3: First Contact

This exercise will step you through Flash ActionScript that will call and handle a function defined on the server. To make things more interesting, the server will also call and handle a function defined in Flash ActionScript. So, there will be a function on the server called sayHelloServer and a function on the client called sayHelloClient. Each of these functions will have a trace function that will show up in the respective trace output windows.

This is a brain teaser, so let's walk through it. When the Flash client calls the server function, the App Inspector's Live Log will display a message that was set on the server. When the server calls the Client function, the Flash MX output window will display a trace in its output window. Let's go one level deeper and send an object from the server to the client. We'll start on the server in SSAS, and then move to Flash MX to script the client:

  1. Create a new folder in the Flashcom/Application folder called myHello.

  2. Create a new main.asc file.

  3. Add the following onConnect handler to the main.asc file. This script automatically accepts all incoming connection requests and instantiates the Client instance:

    application.onConnect = function(clientObject, username) {
      application.acceptConnection(clientObject);

    After the Client object has been instanced by the Application.acceptConnection, you can now start declaring new functions the client can access.

  4. Create a new function called sayHelloServer in the Client instance clientObject. Place a trace action and a return object (in this case, just a string):

    // Define a function for the Client to Call  - send him an object
clientObject.sayHelloServer = function() {
      trace("The client says How Ya Doin, Bucko.. Got Somthin' for ya!");
      return ("FlashCom Server Rocks!");
};

  5. Call the function sayHelloClient that you will script in Flash MX:

          // invoke the function on the Client
      clientObject.call("sayHelloClient");
};

That's it! As you can see by this example, you must declare custom Client functions after the client has connected. As your functions get more complex, you may find it easier to move them outside the onConnect event and into another function. Now, on to Flash:

  1. Open a new Flash movie in Flash MX.

  2. Open the Actions panel on Label 1, Frame 1.

  3. Create a new NetConnection object:

    nc = new NetConnection();

  4. Create the onStatus function for the NetConnection, and place a challenge on the returned status .code. If the connection is successful, call the server function sayHelloServer. Remember, server functions are casE SensItivE:

    nc.onStatus = function(info) {
      trace("LEVEL: "+info.level+"  CODE: "+info.code);
      if (info.code == "NetConnection.Connect.Success") {
            // Call the Server
            nc.call("sayHelloServer", new server_ret());
      }
};

In the nc.call, there is a new object instantiated called server_ret. A function that is called over a NetConnection may not return its results immediately. To compensate for this, an object to receive and handle the result or error must be created for each server function you call. This is called the result object, and it can contain two functions. The onStatus function is invoked if there was an error with the function. The onResult function handles successful function calls. Here is the script to handle a successfully returned function; add this code below the nc.OnStatus function:

// handle any objects returned from Flash's call to the server
server_ret = function () {
      this.onResult = function(value_ret) {
            trace("Message From the Server: "+value_ret);
      };
};

The server returns an object that contains a string value. The returned value is captured in our variable value_ret. This can be any variable name you want. We are only going to use the value to trace it to the output window.

Declaring a function that the server can invoke is simple. You define it as a NetConnection method. The server cannot call a function that is not declared in the NetConnection instance. The following traces output to the Flash MX output panel when it is invoked:

  1. Add this line of code to the bottom of your ActionScript panel to define the function sayHelloClient within the context of the NetConnection:

    // define a function on the NetConnection that will be called by the server
nc.sayHelloClient = function() {
      trace("The Server says.. Yo, Dude!");
};

  2. Connect the NetConnection to the Communication Server to start the show:

    nc.connect("rtmp://192.168.0.1/myHello/myInstance");

  3. Save the Flash file.

Now, you are ready to play. To watch the action, you must have the output window in Flash MX open (F2) and the App Inspector ready. If you want, manually load the Application instance in the App Inspector, or you can wait until your Flash test movie creates the instance. Test your movie using Ctrl+Enter. Your output windows should look something like Figure 11.4.

Figure 11.4. The App Inspector displays the Application instances that are active on the server.

Extending the Client Class

What if you want to create a function on the server that all clients can have access to? You can do this by adding a method or property to the Client object prototype. This is called extending the class.

This example will extend the Client class with a new method called setConnectTime. It will first check to see if the property connectTime is defined, which it won't be, and then it will set it to the current date and time. You try this code using the previous exercise. Place it at the bottom of your SSAS in main.asc:

Client.prototype.setConnectTime = function() {
      if(this.connectTime == undefined) {
        this.connectTime = new Date();
}
return this.connectTime
}

This is now a global method to the entire Client class, just like the Client methods. To use this method, place the call in the onConnect event. This example uses the instance name clientObject, so you could place it in the previous example:

clientObject.setConnectTime();

A new property called connectTime is set. When accessed, it returns the date and time the client connected. As you have already seen, all Client methods within the Client class can be accessed by the Flash client, including this new prototype. You can try it by adding the following line to the onStatus function in the previous exercise:

nc.call("setConnectTimes", new server_ret());

This traces the server time you connected in your Flash MX output window.

Client Object Security and Permissions

One last technique to note is the capability to assign read and write permission to streams and SharedObjects. There are two properties used for this: Client.writeAccess and Client.readAccess. These properties both work on the principle of file access. By default, when a client connects, it is given read and write access to the entire instance. This means it can publish and subscribe to streams, or read and write any SharedObject accessible to the Application instance. You can handle security by setting up different access levels to your SharedObjects and streams. This will be covered in the next two sections; however, this is a good introduction. Let's say you create a SharedObject that you only want the server to write to, but everyone can access it and "listen" to changes made to it. You would set up the SharedObject on the server like this:

server_so = SharedObject.get("mySecureFolder/mySharedObject",true);

Notice the use of a folder here. This actually translates on the server as a folder name, but more importantly, it is an access level. Streams are the same; for example:

myStream = Stream.get("mySecureStreams/myStream");

Now you have two access levels you must lock out: mySharedObject and myStream. To achieve this, you simply set the Client properties when they connect. The following script would allow all clients to read and listen to all resources available; however, the client could only create resources (SharedObjects and streams) in the /pub folder:

application.onConnect = function(clientObject, username){
      clientObject.writeAccess = "/pub";
      clientObject.readAccess = "/";
      application.acceptConnection(clientObject);
}

You can create a list of folders by separating them with a semicolon (;). In the preceding script, a client can only publish a SharedObject in the /pub folder (or access level). The ActionScript on the client would like this:

flash_so = SharedObject.get("pub/mySharedObject",true);

As you can see, the Client object is a great tool to communicate between client and server. Understanding the concept of the instance is the key to the entire Flash Communication Server. Next, you will review the Stream object. Keep in mind that you will instance the Stream class each time you want to use it.

Stream Object

The Stream object is a powerful object that can be used to manage streams coming in and going out from the server. As you have already seen with the client-side NetStream object, a Flash Communication Server stream is a one-way feed of video, audio, or a combination. Communication Server clients can connect multiple streams to a single connection; however, each stream must either publish content to the server or subscribe to content from the server. Streams are collected on the server within an Application instance. They can be prerecorded or live.

Obviously, you cannot watch or listen to a stream on a server, because there is no interface! So what can you do with SSAS and streams? The server can do a number of unique operations that cannot be done on the client. Because of its position in the network, the server maintains priority control over all streams.

This means that it can cancel or overwrite any stream. Some roles that SSAS can take with the Stream object include chaining servers together, acting as a video switcher between live and/or recorded video sources, streaming a play list, or recording a play list or live stream that wasn't set to be recorded by the publisher.

A key difference between the server-side Stream object and the client-side NetStream object is the play() function. The play() method on the server is similar to the publish() method on the client. The play() function publishes content to a stream. You might ask, "If the server does not have a video or sound device, how can it publish?" The play() function takes its video sources from one of two places: prerecorded Flash video (FLV) or live streams being published by a client.

Consider the play() function as a play list that can control what a stream is sending. Let's say you have three prerecorded Flash videos that you want to sequence together. video1.flv would play for 10 seconds, then video2.flv would play for 10 seconds, and then video3.flv for 10 seconds. Using multiple play() functions in SSAS makes it easy to build this sequence. Here is some sample script that would achieve that:

startStream = function(){
    // Create the stream
    var my_stream = Stream.get("serverStream");
    // Start the playList
    my_stream.play("video1",0,10);
    my_stream.play("video2",0,10);
    my_stream.play("video3",0,10);
}

When the function startStream is called, the stream serverStream is created, and the play list begins. This play list starts immediately, even if no client is connected. The stream is running in real time. If a client subscribes to the stream 15 seconds after the function was called, the client would start in the middle of video2.flv.

You could also do this with a live stream. Let's say you want to play video1, then video2, and then switch to a live stream. The script would look very similar, except video3 would be replaced with the name of the live stream being published to the server by a client. Take a look:

startStream = function(){
    // Create the stream
    var my_stream = Stream.get("serverStream");
    // Start the playList
    my_stream.play("video1",0,10);
    my_stream.play("video2",0,10);
    my_stream.play("someClientStream",0,-2);
}

The play() function has similar parameters to the client side. The first parameter is the stream name. This can be the name of a live stream being published by a remote client or server. startTime is the next parameter. With a recorded stream (FLV file), this references the start time in seconds to begin the stream. If you are referencing a stream that is being published by a client, there are two values you can use. If startTime is set to a value of -1, Flash Communication Server tries to connect to a live stream published remotely. If the stream does not exist, it waits until the stream is created by the publisher. If you set the value to -2, Communication Server attempts to look for a prerecorded FLV video on the server with the same name. If there is no live stream and no recorded file, Communication Server creates a stream and waits for someone to publish to it.

The –2 option is great if you are preparing a live broadcast and need to have some filler while the stream is being set up. The reset parameter follows the startTime and expects a Boolean value. It clears the stream if it is set to true. The last option allows the play function to source a stream from a NetConnection to another server. This is a key element for chaining servers together. Let's look at some scenarios of how you can use the Stream object, including chaining servers to increase user and bandwidth capacity.

Live Video Switcher

As you saw, the Flash Communication Server can switch between live and recorded streams using a preset play list. This is a great technique, but you may find you want some additional control over what subscribers are seeing. At this point, you will have to create some sort of Switching interface in Flash MX.

Figure 11.5 represents a scenario of four live streams being published to Flash Communication Server by four separate Flash clients. The Flash clients that are on the receiving end are only receiving one stream. Using SSAS, you could automatically cycle the source of the outbound stream from any of the four inbound streams similar to the previous example. This would be great with a security-camera application that required you to cycle between a number of video sources. However, you want more control over when the streams are switched.

Figure 11.5. In this situation, each subscriber would require only one stream to be connected to the server, not four. As interesting as this is, it wouldn't have much practicality in a real-world communication situation.

A better solution would be to build a Flash application that could control the SSAS and allow you to manually "switch" between video sources. Figure 11.6 isn't real, but it demonstrates how you could build a Flash-based video switcher to control what the live stream is.

Figure 11.6. A fictitious Flash video switcher application that will control the play list on the server.

In this example, there are four live streams and one prerecorded advertising stream. The operator of this interface can control what is being sent to the server stream.

Chaining Servers

Chaining servers is a great technique for distributing the load on your server. If your Flash Communication Server license only allows 10 users and you need 15, you can use this redistribution technique. The Flash Communication Server is a point-to-point network. This translates into the server reserving enough bandwidth for each user subscribing to a stream. This is different from a satellite TV approach, which uses a point-to-multipoint connection. With satellite TV, the broadcaster sends out its signal and, it doesn't matter how many people are watching it, there is no additional load on the satellite if one person is watching or one million people are watching.

When you chain servers together, you can increase the number of users that can watch your stream, and you increase the bandwidth available. In Figure 11.7 there are three servers chained together. Each server has a 10-user license. This would allow a total of 24 Flash players to connect to the live stream. Each server would reserve one publish stream (outbound) for another server. Each server would use another stream as its subscription (or inbound) stream.

Figure 11.7. The Flash Communication Server can be chained with other servers to increase bandwidth and user capacity.

A fictitious Flash video switcher application will control the play list on the server.

You can achieve this very easily. First, you need to connect the server to another server, and then you simply connect the play function to a remote server stream. Let's use the same script from the earlier example, but this time, video 3 will be sourced from another Flash Communication Server stream:

startStream = function(){
    // establish a NetConnection to a remote application instance that
    // is streaming.
    nc = new NetConnection();
    nc.connect("rtmp://[remote server]/[remote app]/[remote instance]");
    // Create the stream
    var my_stream = Stream.get("serverStream");
    // Start the playList
    my_stream.play("video1",0,10);
    my_stream.play("video2",0,10);
    // receive the 3rd video from a remote server
    my_stream.play("someOtherServerStream",0,-1, false, nc);
}

As you can see, the syntax is not that complex. Sourcing streams is another great feature of Flash Communication Server.

Video Recorder

There is one more thing you can do with the Stream object: record. You can assemble a series of streams into a single recorded stream that can be played back without a play list. The record() method records the play list into a single FLV file, named with the stream name. In the following code sample, a file called serverStream will be created in the folder /myApp/streams/myInstance/ serverStream.flv:

startStream = function(){
    // Create the stream
    var my_stream = Stream.get("serverStream");
    // Start the playList
    my_stream.record();
    my_stream.play("video1",0,10);
    my_stream.play("video2",0,10);
    // receive the 3rd video from a live source
    my_stream.play("someClientStream",0,-1);
}
Other Methods of Stream

Like the client-side NetStream, you can also invoke functions through the stream using the .send method. You can monitor buffer time and set the buffer time, just like on the client. Buffer time is the amount of memory allocated to preload a stream before it is played. You can also use the length function to determine the length of a prerecorded FLV file.

Stream is an integral part of the Flash Communication Server. It is very powerful and extremely scalable. Security is achieved as with SharedObjects through access levels, or folders. For more details on security, review SharedObject security in the next section.

SharedObject (SSAS)

The SharedObject programming model is clearly the most exciting and most powerful feature of the Communication Server. Some might consider the capability to stream video as the best part, but after you understand the power of SharedObjects, your imagination will work overtime with the possibilities. The server-side SharedObject is like the client-side SharedObject, with a few additional features.

A SharedObject stores two things: objects and methods. They can be accessed by any connected Flash or server client. These clients are completely synchronized with each other. Any client or server with appropriate permissions can change, add, or remove data. These activities invoke Flash Communication Server to announce the change to all connected clients. These clients respond to the announcement appropriately by refreshing their local memory cache of the SharedObject. Client-side functions can be invoked through broadcast messages over the SharedObject.

SharedObjects can be persistent or temporary. They can be created by the server or by a client connected to the server. SharedObjects can be locally owned or owned by another instance. This means that you can share data across instances and applications. If that isn't enough, you can also access SharedObjects owned by an instance on a different server somewhere else in the world! This is a technique called proxied SharedObjects.

These next few sections will introduce you to some advanced concepts of the SharedObject as it is accessed using server-side ActionScript.

SharedObject Slots

Data is stored in a concept called slots. Slots are name and value properties contained as attributes of the SharedObject.data property. This may be a little confusing at first, but when you get used to the idea, it makes a lot of sense. Consider the data property of a SharedObject like the _root of a directory. Within the root, you can create folders that contain files. Folders can also contain subfolders, and so on. Visualizing this tree will help you understand the concept. A slot can be any valid ActionScript object. This includes arrays, objects, recordsets, or even simple variables. The exercise in Chapter 8, "STEP 8: Collaboration with SharedObject()," clearly demonstrated simple name and value variables as independent slots of the data property. The user access array you created earlier in this chapter could be completely stored in a persistent SharedObject, if you wanted. Let's take a look at how you would do that.

This was the array you created earlier:

user_array = [];
      user_array.push({uname:"kevin", password:"bird"});
      user_array.push({uname:"colin", password:"tank"});
      user_array.push({uname:"sharon", password:"craft"});
      user_array.push({uname:"sandy", password:"car"});

Placing this array into a SharedObject slot is simple.

Note

Unlike the client-side method, in server-side ActionScript, you must use a setProperty method to add or edit slots. Here is some sample SSAS to add/edit a slot called user_array in the SharedObject secureData/systemObject:

MySystemObject_so = SharedObject.get("secureData/mySystemObject", true);
MySystemObject_so.setProperty("userData", user_array);

Reading SharedObject data also requires a unique method, getProperty. Here is an example of transferring the entire array from the SharedObject to a local server variable:

var myServerVar = MySystemObject_so.getProperty("userData");

SharedObject Synchronization

This all happens in real time through a powerful process of synchronization messaging. The Flash Communication Server sends messaging "objects" to each connected client and server. This object is an ActionScript array of objects called information objects. This is a similar concept you see with NetConnection or Stream. When data changes in the SharedObject, everything that is connected is informed of the data change by the Flash Communication Server. Data can be simultaneously changed, added, or removed by the server with SSAS, or by any number of connected clients using ActionScript or SSAS.

At first glance, it might seem very complicated, primarily because of the array of objects. The information object is handled on each client and the server by the onSync event. The process was demonstrated in Chapter 8 where there were multiple clients changing data at the same time.

The array can contain a batch of change events. It does not contain data. You are responsible for building a handler on the client and the server for the data change notifications. This might include transferring a SharedObject slot value to a local variable, or affecting an object appropriately. The array is useful (on the client) if it becomes disconnected and has to reconnect. Upon reconnect, the array may have a number of messages inside that it must handle.

The following onSync handler script template demonstrates how you can handle the information object both on the client and on the server. You must loop through the array and challenge and handle the code property on each loop. This template will handle the four possible cases of the code property:

this.so.onSync = function(info) {
    trace("Synchronizing Data");
    //
    // Use this structure as a prototype for your onSync Handlers.
    // Loop through the Array of Objects using the IN operator
    //
    for (name in info) {
           trace("[sync] Reading Array Object #"+name+"
           code("+info[name].code+","+info[name].name+")");
           //
           // ::: The following switch handles code values returned by the object
           // Place Code Here
           //
           switch (info[name].code) {
           case "change" :
                  trace("::Handle a change of data by another client");
                  // Place Code Here
                  break;
           case "success" :
                  trace("::Handle successful change of data from this
                  server");
                  // Place Code Here
                  break;
           case "reject" :
                  trace("::Handle a rejected SharedObject write operation");
                  // Place Code Here
                  break;
           case "clear" :
                  trace("::Handle an initialization of the SharedObject");
                  // Place Code Here
                  break;
           case "delete" :
                  trace("::Handle deleted Attributes");
                  // Place Code Here
           }
           // ::: End the Switch, continue Looping through the Information
           Object
      }
      // ::: Complete the onSync Handler
};

The whole synchronization process is explained in detail in Chapter 8.

SharedObject Security

You can control the security of SharedObjects using the Client properties Client.writeAccess and Client.readAccess. Review the Client object section earlier in this chapter for some example script. SharedObjects, like the Stream object, can be filed into access levels, or folders. This can only be done when they are first created.

For maximum security, creating a SharedObject on the server is the best practice. If you can, create the SharedObject on the application.onAppStart. Create a strategy for storing SharedObjects. For example, use a common folder for all sensitive SharedObjects and a public folder for all non-sensitive objects. Remember, you can have as many SharedObjects as you need. Don't try to place sensitive data in slots of one big general SharedObject. It just cannot be secured that way.

Proxied SharedObjects

SharedObjects can also exist within other Application instances, or even on different servers altogether. Connecting to a remote SharedObject from the server is a process called proxied SharedObject. The concept isn't that difficult to grasp. When an Application instance connects to a SharedObject within another instance or application local or remote, it makes that SharedObject available to all of its connected clients.

The process is similar to an Internet service provider, or your network router. When you dial up your computer to your provider, you have access to everything your provider is sharing. If you then have a router in your home or office, you redistribute that feed to workstations in your network. This can be called a proxy server. To connect, you must route your request through the proxy server. The Flash Communication Server Application instance is no different. When the SharedObject is connected, it is available to all of its connected clients, unless you have placed it within an access level (or folder). Connecting is simple.

First, you make a connection to a remote server, or Application instance, using the SSAS NetConnection object. This can be done in the application.onAppStart function. It is not recommended to have it within the onConnect, because each time a client connects, the server will reconnect. You could write some script that challenges the NetConnection.isConnect property. The following script uses this technique:

application.onAppStart = function() {
      nc = new NetConnection();
};
application.onConnect = function() {
      if (not nc.isConnected) {
            nc.connect("rtmp://[remote server]/[remote app]/[remote instance]");
            // - or -
            nc.connect("rtmp:/[local app]/local instance]");
      }
};

When your server is connected, you then attach the SharedObject to the NetConnection instance. The following script is the exact script you saw in the preceding; however, it is not stored within its Application instance:

mySystemObject_pso = SharedObject.get("secureData/mySystemObject", true, nc);
mySystemObject_pso.setProperty("userData", user_array);

The suffix _pso was added to the SharedObject to signify proxy SharedObject. It is not required, but it helps you keep things straight.

SharedObject Methods

If you weren't impressed enough already by the SharedObject model, this might just add the cherry to the top. You can create ActionScript functions and assign them to a SharedObject. Think about that for a moment. If you can create a function and assign it to a SharedObject, that means a Flash player can invoke a function on another Flash player! SharedObject functions are primarily used for messaging. You cannot "call" a SharedObject function like you can a remote Flash function. You use the SharedObject's send method to invoke the function. You cannot create a SharedObject function using server-side ActionScript. It can only be created by the client, and the server doesn't receive any response from the client on success or failure of the send method; therefore, it is asynchronous.

To execute a SharedObject method on the Flash client using the send method, use the following code:

var my_so = SharedObject.get("SharedObjectFileName", true);
my_so.send("client-so-method");

Creating SharedObject functions will be covered in the next chapter; however, here's a sneak peak to create a SharedObject function on the Flash client:

so=SharedObject.getRemote("myObject", nc.uri, true);
so.connect(nc);
so.data.myMethod = function() {
      trace("Hi There from your Friendly SharedObject.");
};
SharedObject Locking

SharedObjects can be temporarily "locked" only by the server. Locking a SharedObject allows the server to perform operations on the SharedObject without triggering the onSync events for each player. Locking also allows you to ensure that there are no SharedObject write actions while the server does what you want it to do. During the lock, each change that is made is batched. Unlocking the SharedObject engages the batch to announce the changes to the connected clients.

There are two methods associated with locking: so.lock() and so.unlock(). Wrap your SSAS operations in these functions and you will execute a lock and release.

Other SSAS Methods Unique to the Server Side

Because the server-side version has direct access to the SharedObject, you can perform a few additional methods to the data such as some clean up methods like .clear, .purge, and .flush.

.clear deletes all properties (slots) of any a object. It doesn't take any arguments. This method is useful if you create a temporary SharedObject and want to clear all traces of it from the server. Here is the .clear method:

var my_so = SharedObject.get("SharedObjectFileName", true);
my_so.clear();

.purge is useful to clean up any empty properties or properties that are older than the current version (more on versions shortly). The flush function transfers the memory-version of the object to a file. You can only do this with persistent SharedObjects. The file is located in a SharedObjects folder within the Application folder. Like the Streams folder, this folder contains subfolders referencing any instance names of the application.

.flush forces Flash Communication Server to dump the memory version of a persistent SharedObject to the file version. It's like hitting the Save button when you are writing a book. This is a good habit to get into if the synchronized data you are storing is extremely important and a sudden server halt (such as a power failure or someone clicking that Halt button in the Administration Console) would kill the data. You can do it using the setInterval tag,or after a major operation such as a database query.

Flash Communication Server installs with two additional objects that are used with Flash Remoting MX. These two objects are NetServices and RecordSet. They are discussed in detail in Chapter 13, but we will make a brief mention of them here to keep everything together.

NetServices Object

Using the Communication Server, you can expose databases and other services to the Flash player. This is achieved through technology called Flash Remoting MX. Flash Remoting MX operates on the standard HTTP or secure HTTPS protocols using a binary format called Action Message Format (AMF).

The NetServices class contains the methods required to call services on remote application servers. Remote application servers can provide database access and access to other server-level resources such as email or LDAP.

Making a Flash Remoting MX call requires a server that is compatible with Flash Remoting MX. These servers are discussed in Chapter 13. NetServices gives you the tools to connect and call remote service methods that can return any ActionScript object including the new RecordSet object.

RecordSet Object

The RecordSet object is a series of 17 unique methods that give you familiar tools to interact with a database query result set. Using the concept of columns and rows, you can sort, get column names, and even search through the RecordSet easily.

RecordSet objects can be transferred into SharedObjects for distribution to connected clients. A complete breakdown of the RecordSet methods are included in the Quick Reference appendixes. Example applications using the RecordSet object can be seen in Chapter 13 and Appendix E,"Useful ActionScript Templates Quick Reference."

Timed Events Using Intervals

ActionScript intervals were introduced in Flash MX to allow Flash developers to schedule the call of functions at specific timed intervals. The functionality is also available within SSAS. Intervals on the server can be used fully to let you call functions that may clean up the SharedObjects with a purge() method, or flush() them periodically to the hard disk. You could also develop an interval to capture a still image of an incoming stream to create a time-lapse photography effect. Intervals are easy to set up. This example calls the captureMyCamera function every two seconds:

intervalID_itv = setInterval("captureMyCamera", 2000);

It is important to use a variable to run this setInterval function because setInterval will return an ID value that you need if you want to shut it off. When you are finished with the interval, you can clear it using the clearInterval function, referencing the intervalID used in the previous example:

clearInterval(intervalID_itv);


Debugging Techniques

As you may have noticed already, server-side ActionScript is difficult to debug. Macromedia Dreamweaver MX does not include an ActionScript interpreter like the Flash ActionScript Editor. Although it has code hinting for SSAS, it does not have the handy Code Format (or Code Cleanup) control that Flash MX has.

Testing SSAS is tricky because you may need a number of elements in place, such as multiple Flash players, Flash Remoting MX Servers, and database servers. You have to watch Flash ActionScript using Flash MX, and watch server ActionScript using the App Inspector. Trace activity happens in the App Inspector, which is a great tool; however, it requires some tricky multitasking to place it in your workflow.

Clearly, the best form of watching your script is the Live Log window of the App Inspector. This tool allows you to manually instantiate your application. The problem is that you have to create an instance before you can see the Live Log. If your script has errors in it, a warning icon will appear in the active instance window. Double-clicking that icon displays any compile error messages received by the SSAS interpreter. But watching the Live Log will give you the best idea of where the error is occurring.

A great trick to spot errors before you save your SSAS is to leverage the ActionScript interpreter inside Flash MX. When you have updated your SSAS, copy the entire script into the ActionScript panel within a new Flash document. Use the Check Syntax tool (click the checkmark at the top of the ActionScript panel or press Ctrl+T). This parses the SSAS and reports any syntactical errors. Also, use the AutoFormat tool (next to the checkmark) to format your code so it's easier to read.

When you are finished, copy everything back in to your SSAS Editor or Dreamweaver MX, save the file, and reload your application. It would be a great future feature of Dreamweaver MX to include the ActionScript interpreter in its next release (hint, hint).

One last tip is to make use of onStatus as much as you can. Trace the activities to the Live Log. There is a complete list of every information object sent by the Flash Communication Server in Appendix C,"Information Objects (Server and Client) Quick Reference."


Summary

That's server-side ActionScript in a nutshell. This is your first introduction to it, but as you can see, it is very similar to Flash ActionScript. Just remember: It is case sensitive!


Chapter 12. Client-Side (Flash) ActionScript

Now that you have a grip on what's happening on the server, you can focus on controlling your Macromedia Flash Communication Server MX application using Flash ActionScript. A deep exploration of the Communication objects and the Flash Communication UI components will make up the bulk of this chapter. The chapter will also discuss messaging, scripting techniques, security, hardware devices, and some simple debugging techniques you can use.


Macromedia Flash MX Communication Tools

When you install the authoring components into Macromedia Flash MX, a series of new elements will be added to your Flash MX authoring environment:

  • Communication App Inspector. A tool used to connect and control application instances that are running on the Flash Communication Server. It provides the Live Log window used to monitor trace activity from server-side ActionScript (SSAS).

  • Flash Communication UI Components. A series of pre-built Communication User Interface components that allow you to quickly build applications for Flash Communication Server. As for most Flash UI components, you can control these using ActionScript. Each UI component has a custom ActionScript object with methods and properties. Each component also responds to the methods and properties associated with the MovieClip class, such as the _visible property.

  • Flash Communication UI Component Dictionary. A detailed library describing the component ActionScript object's method, properties, and events. The dictionary is available through the Reference panel (Shift+F1), as well as through the Actions Toolbox in the ActionScript Editor (F9).

  • Flash Communication Object Dictionary. A detailed library describing the objects that you can use with the Flash Communication Server. This dictionary is available through the Reference panel (Shift+F1) and the Actions Toolbox in the ActionScript Editor (F9).

  • NetServices and RecordSet Class Files. New ActionScript objects that connect the Flash player with Flash Remoting MX-enabled services. The RecordSet object is a new object that lets you build and interact with a standard database query object. These classes must be manually included into your ActionScript.

  • NetConnection Debugger. A new debugging utility that lets you monitor activity between the Macromedia Flash player and Communication Server or Flash Remoting MX server.

As you can see, many new features are now available that extend Flash MX authoring abilities. This chapter will step through these elements.

Note

For your convenience, Appendixes B, C, and D contain details of every Flash ActionScript method, property, and event, including full details of the ActionScript objects for the Communication UI components.


The Communication ActionScript Objects

"Trojan horse" is one term that can be used to describe the Communication Objects in Flash MX and Flash Player 6. You see, Flash Player 6 was shipped with full support of these new objects before the Communication Server arrived. The Camera object could always connect to your camera. Local persistent SharedObjects could be used; however, this fact didn't even make it into the Flash MX online dictionary or manual. Even LocalConnection wasn't in the original documentation. Everyone got curious when they saw the new settings options and Privacy panel when a Flash application was right-clicked in Flash Player 6. The biggest question was, "What does the camera and microphone thing do?"

The Communication Server brought with it the ActionScript references for these objects. When you installed the Communication components into Flash MX, an entirely new set of ActionScript code hints and dictionaries were installed in the ActionScript panel's Toolbox under the heading Communication, as shown in Figure 12.1.

Figure 12.1. The Communication Dictionary can be found in the ActionScript panel's Toolbox (F9), or the Reference panel (Shift+F1).

Included in this tree, amidst the new Communication objects, are native Flash MX objects that do not require Flash Communication Server to be used. So the label "Trojan horse" is appropriate in a good way. Just when you thought you knew it all in Flash MX, you get another fix with the Communication Server.

Because this is the first time you've ever seen these objects, we'll step through them in some detail, but there isn't room to cover every feature here. Instead, Appendix B,"Macromedia Flash ActionScript Objects Quick Reference," details every method, property, and event for each Communication object.

Camera Object

The Camera object controls the Flash player's internal video capture driver. This driver accesses supported video sources attached to a client's computer, such as a web camera, a Firewire source, or supported screen capture utilities. The settings that can be controlled with ActionScript include frame size, frame rate, and bandwidth consumption. Limited control over the internal video compressor lets you also set the keyframe rate.

A great feature, even without the Communication Server, is the ability to use the Camera object to trigger events. That's right, you can use the camera input to monitor motion. When it detects movement (or a lack of movement), an event can trigger ActionScript to do something. When you add the Flash Communication Server to the camera feed, you can publish video to the server. This will make the camera feed recordable. You can also snapshot still images or record a series of still images captured automatically over time.

The key method to using the Camera object is Camera.get(), which tells the Flash player to access a camera attached to the client's computer. This method triggers the Privacy panel, informing the user that the Flash player is accessing the camera. You can also trigger this panel using the Security object, which will be discussed later in the chapter.

Exercise 12.1: Displaying the Camera

To display the camera on the Flash stage, you need an embedded Video object. Video objects are available from the Library panel, as shown in Figure 12.2. Let's do a simple exercise to display your web camera on your Flash stage.

  1. Create a new Flash document in Flash MX.

  2. Open the Library panel (F11), and click the Library panel pull-down menu (circled in Figure 12.2).

  3. Add a new video to the library.

  4. Drag the Video object to the Flash stage.

  5. Assign it an instance name of my_video in the Properties panel. Make sure you use a name with the suffix _video to enable video code hinting in the ActionScript Editor.

  6. Open the ActionScript Editor (F9).

  7. Click on Frame 1, Layer 1 in the Timeline, and add the following code in the ActionScript Editor:

    my_camera = Camera.get();
my_Video.attachVideo(my_Camera);

  8. Save your document, and test your movie (Ctrl+Enter).

    When the movie runs, you will be prompted by the player to allow the Flash player to access your video camera. When you accept, you will see your camera on your screen.

  9. Try accessing the motion sensor. Add the following to set up the event handler:

    my_camera.setMotionLevel(10, 500);

    This sets the motion sensitivity to 10 (out of 100) and the timeout to 1/2 second (500 milliseconds). If you are curious to learn more about this feature, refer to Appendix B.

  10. Add the following code, and then save and test your movie again:

    my_camera.onActivity = function(value) {
if (value) {trace("Someone is there");}
 else { trace("Come back and play");}
 };
}

    When you test your movie this time, keep an eye on the Flash Output window (F2). Hold very still, and then move in front of the camera. When you move, you will see trace actions in the Output window. When you stop moving, the onActivity property is set to false and trace actions display in the Output window.
Figure 12.2. Add embedded video using the New Video item in the Library's pull-down menu.

The camera also has an onStatus event. This event is triggered when the user allows or denys access to the camera. You can overwrite the onStatus function to handle the information that will be returned with a simple script, like this:

my_camera.onStatus = function(infoObj){
trace("level: " + infoObj.level + "code: " + infoObj.code);
}

Two information objects can be returned: Camera.muted and Camera.unmuted.

You have already seen how to connect your camera to the publish stream in Exercise 7.4 in Chapter 7, "STEP 7: Streaming Video with NetStream()." It is as simple as attaching the Camera feed to the NetStream.

For a full list of the Camera objects, refer to Appendix B.For some tips on troubleshooting your camera, refer to the section on cameras and microphones near the end of this chapter.

Capturing Your Desktop as a Video Source

With third-party software, you can use the Camera object to capture a small window on your desktop as your video source. The Camtasia Recorder (see Figure 12.3) from TechSmith operates like a PC camera when it is in Live mode. The software is available for the Microsoft Windows platform only. To the Flash player, it appears as a standard Video for Windows capture device.

Figure 12.3. The Camtasia Screen Capture tool from Techsmith is available for the Windows platform only.

This means that you can use Flash to distribute a live feed of your applications or your desktop. The only limitation is that you are restricted to a 320x240 window area.

To select the Camtasia Video Capture Driver on your Flash player, access the player's Settings panel by right-clicking on the Flash player and choosing Settings from the menu. Select the Camera tab. If your Camtasia Recorder is installed correctly, you should see an entry in the Camera pull-down menu for the Camtasia Video Capture Driver, as shown in Figure 12.4.

Figure 12.4. Select the Camtasia driver from the Flash player's Camera Settings panel.

Camtasia is available on the Internet from the Camtasia web site (http://www.Camtasia.com/).

Microphone Object

The Microphone object controls access to the microphone input on the client computer. Like the Camera object, the Microphone object controls such capture settings as sample and gain. You can set the Microphone object to also trigger events when it detects sound or silence. The Flash Communication Server is required to record or transmit the microphone source to other Flash clients; however, the Microphone object can be accessed locally without the server.

The Microphone object operates very similar to the Camera object. In fact, it is identical. To attach your microphone to output to the Flash player, add the following code to your Flash document:

my_mic = Microphone.get();
_root.attachAudio(my_mic);

The Flash player cannot access any other audio input port that may exist on your audio card, such as the CD or Line In. You are also restricted from distributing local documents, such as MP3, WAV, or AIF files, to the NetStream encoder. This said, you can always cross your inputs within your operating system.

The Microphone object, like the Camera object, has two events: onActivity and onStatus. They operate exactly the same way as the Camera's, except they sense sound instead of motion.

The onStatus event is triggered when the user allows or denys access to the microphone, and you can overwrite the onStatus function the same way you did with the Camera object. Two Information objects can be returned: Microphone.muted and Microphone.unmuted.

You have already seen how to connect your microphone to the publish stream in Exercise 7.4 in Chapter 7. It is as simple as attaching the Microphone feed to the NetStream object.

For a full list of the Microphone objects, refer to Appendix B.For some tips on troubleshooting your microphone, refer to the section on cameras and microphones near the end of this chapter.

NetConnection Object

The NetConnection object maintains a persistent two-way connection between the Flash player and the Flash Communication Server. NetConnection is the cornerstone of any communication application. The SharedObject and NetStream objects use a NetConnection object to exchange streams and ActionScript objects with the server. The NetConnection object can handle the transport of multiple SharedObjects and multiple one-way streams. It also handles broadcast messages within the streams and the SharedObjects.

Communication between client and server is achieved using the Real Time Messaging protocol (RTMP) built by Macromedia specifically for Flash Communication applications. RTMP is a binary format, but it cannot be encrypted. To establish a connection between the client and the Communication Server, use the connect method once the NetConnection object has been instantiated to a local variable:

nc = new NetConnection();
nc.connect("rtmp:/myApplication/myInstance", "my name", "my Pasword");

Note

The single forward slash, /, in the RTMP connection string is the correct way to reference a Flash Communication Server, if it is on your local computer. If you are accessing a remote server, use a double forward slash, //, as in:

rtmp://[servername]/[application]/[instance]

The connect method invokes the application.onConnect method on the server. As you saw in Chapter 11, "Server-Side ActionScript (SSAS)," the onConnect method can accept any number of parameters you need. In the previous code sample, parameters for username and password were sent with the server string.

Uniform Resource Identifier (URI)

The Flash player establishes a RTMP connection by referencing the server with a Uniform Resource Identifier (URI). The URI can be an absolute value or a relative value.

An absolute URI looks like this:

rtmp://www.myServer.com/myApp/myInstance

The absolute URI should be used if the Flash Communication Server uses a different URI than the calling SWF movie, which is usually the case if your SWF movie is on a different server than the Flash Communication Server. This is true for both development and production server setups. The downside to using an absolute URI is that the ActionScript would not be portable without modification to install on another server, such as your production server. Absolute URI's use a double forward slash, //, following rtmp:.

A relative URI uses only a single slash before rtmp: and looks like this:

rtmp:/myApp/myInstance

The relative URI can be used if your Flash Communication Server occupies the same URI as the calling SWF movie, which is usually the case if your SWF movie and Flash Communication Server reside on the same machine. Most development environments are set up with the SWF and Communication Server sharing a single machine. Adopting this method will ensure your code stays as portable as possible, so that when your application is complete you don't need to change any code to deploy it to your production server.

NetConnection onStatus Event

Like the Camera and Microphone objects, NetConnection also has an onStatus event. This event is often used to ensure a connection is present before starting operations on it, as in:

nc.onStatus = function(infoObj){
trace("level: " + infoObj.level + "code: " + infoObj.code);
}

The NetConnection status handler can receive a large number of Information objects, but only three code values are critical for most communication applications:

  • NetConnection.Connect.Success Sent by the SSAS function application.acceptConnection(). When this value is received, the connection has been accepted by the server and can start handling SharedObjects and NetStreams. Test for this code value first, and then start connecting the required resources only after receiving it.

  • NetConnection.Connect.Rejected Received when the SSAS function application.rejectConnection is called. Usually this function is called when the client has passed incorrect credentials to nc.connect.

  • NetConnection.Connect.Closed Received when the network connection has failed or the server is unreachable. You should monitor this code closely and take action informing the user that there is a problem with the connection to the server. The code also will be sent when the server calls the application.disconnect() method.

There is a generic onStatus "catch-all" script template in Appendix E,"Useful ActionScript Templates Quick Reference." You can use this script to handle all NetConnection Status changes. The script is also available through the book's web site (http://flashcom.PangaeaNewMedia.ca/).

Calling Remote Functions Over NetConnection

Custom NetConnection methods add routines to the NetConnection object prototype or instance. Adding methods to the object exposes them to the server. This means that the server (SSAS) can call functions or properties that you set in Flash. This is a great technique with a million uses. For example, you could use NetConnection methods to enable a client's web camera or control the Timeline play head on a client. This technique could also be used for instant notification or messaging.

Creating a function within the NetConnection object is simple. Here is an example:

nc.turnOnCamera = function("message"){
      trace("The Server Says: " + message);
      my_video.attachCamera(Camera.get());
return("Camera has been enabled!");
}

The server calls this function like this:

application.onConnect = function(clientObject){
application.acceptConnection(clientObject);
clientObject.call("turnOnCamera", new clientRet(),"I Can See You");
/* This function will be closed in the next step */

Similar to the SSAS Client object, the function executes remotely. The server may not have the results fast enough to process them immediately, so the results are sent to a client results object called clientRet. This return function can contain two events: onResult and onStatus. This script listing will follow the Client object call made earlier:

      clientRet= function() {
            this.onResult(value_ret) = function() {
            trace("The Client Says:" + value_ret)
            }
      }
/* Close the application.onConnect() Function earlier */
}

When the client has completed the request, it returns a result object to the server. The onResult method will be invoked within the clientRet object.

Because the NetConnection is a two-way exchange, functions defined within the object are the only client-side functions that can return ActionScript objects to the server. SharedObject and NetStream functions are only one-way and cannot return a result to the caller server.

ActionScript objects transferred over the NetConnection are exchanged using the Action Message Format (AMF) over RTMP. Handled by the server and the Flash player, this format is completely transparent to the developer. AMF is also used transparently with Flash Remoting MX in the NetServices object.

For a full list of the NetConnection objects, refer to NetConnection in Appendix B.For a detailed listing of all NetConnection Information objects, refer to Appendix C,"Information Objects (Server and Client) Quick Reference."

NetServices Object (Flash Remoting MX)

The NetServices object is used to transfer ActionScript objects with Flash Remoting MX services using AMF over traditional web HTTP or HTTPS. The object is primarily used to call methods on remote services, such as an application server connected to a database, or other servers, such as a mail or LDAP server. A NetServices connection is nonpersistent, meaning that it only connects when a service is called or returned. This is very different from the sustained connection achieved by the RTMP protocol and the NetConnection object.

NetServices (or Flash Remoting MX) is available for both the Flash Communication Server and the Flash client. The server-side and client-side NetService objects are identical and perform the same operations. In Flash MX, you are required to manually load the NetServices Libraries before you can use them.

To load (or include) the NetServices Libraries in Flash MX, place these lines at the beginning of your ActionScript:

#include "NetServices"
#include "NetDebug" // used to engage the NetConnection Debugger

There are only three NetServices methods:

  • SetDefaultGatewayURL

  • createGatwayConnection

  • getServices

These methods are responsible for defining the connection location and the service to connect to. The listing below references a remote service called myFolder.myService on the server www.myRemotingServer.com:

NetServices.setDefaultGatewayUrl("http://www.myRemotingServer.com/flashservices/gateway");

gatewayConnnection = NetServices.createGatewayConnection();
myServiceRef = gatewayConnnection.getService("myFolder.myService", this);

The Flash Remoting MX service is instantiated in the variable myServiceRef. Flash now has access to any method (service function) defined within the service. In Chapter 14, "Server Administration," you will learn the details of Flash Remoting MX to create and serve service functions to the Flash Communication Server and Flash Player 6.

This process calls the Flash Remoting MX service functions from Flash Player 6. If you are using the SSAS NetServices, none of this is required. The Flash Communication Server can be used as a mediator to distribute content returned by Flash Remoting MX providers.

For full details of the NetServices (Flash Remoting MX) objects, refer to Appendix B.Also refer to Chapter 13, "Accessing External Data," for examples and details.

NetStream Object

The NetStream object is a one-way streaming connection between the Flash player and the Flash Communication Server. The NetStream object is used to transmit or receive video and audio, and to broadcast messages between the Flash player and the Flash Communication Server.

The Flash player can attach an audio or video stream to Flash MovieClips or embedded Video objects, just as it directly connects the camera and microphone sources.

You can open as many one-way NetStreams as your application requires. The following script can be used to connect two NetStreams to the same NetConnection (nc):

publish_ns = new NetStream(nc);
subscribe_ns = new NetStream(nc);

This listing does not determine which way the streams are going. It simply instantiates the object to local variables. Each instance of the NetStream object shares the NetConnection object to communicate with the server. The total bandwidth available is divided between each stream equally.

Publishing a Stream

Publishing (on the Client) is the process of sending a one-way stream originating from the Flash player to the server. The stream will send any valid camera or microphone source or ActionScript object of any type. The Flash player can publish to a Flash Communication Server only. It cannot publish directly to another Flash player. The SSAS object Stream can publish a prerecorded stream or be used to redirect client streams. This process is examined in Chapter 18, "Build Training and Education: The Virtual Classroom." The following code demonstrates how to use the Flash player to send (publish) a camera and microphone stream to the Flash Communication Server:

// attach the Microphone and Camera to the publish_ns stream
publish_ns.attachAudio(Microphone.get());
publish_ns.attachVideo(Camera.get());

At this point, the stream has still not been identified to the server. The publish method establishes the connection and determines it will be traveling to the server with the name myStream.

// start publishing the combined camera and microphone feed
publish_ns.publish("myStream", "record");

The second parameter informs the server what to do with the stream in terms of recording. There are three options available:

  • record Saves the live stream to the server as a FLV file.

  • append Adds the live stream to the end of an existing FLV file.

  • live The default setting, and the server will not handle the incoming stream.

The example code engages the recorder and starts saving the stream to a file called myStream.flv in the application's stream folder.

If you review the App Inspector, you will see an entry in the Streams tab showing your stream being published. You will also see clients who are subscribing to it.

At this point, permissions assumed, any client connected to the application instance can subscribe to the stream called myStream. The next section will create a real loopback that will subscribe to the same stream it is publishing. This effect could be achieved using the Camera.loopback() function. For this example, however, the stream will actually take a round trip from player to server and back to the player.

Subscribing to a Stream

Subscribing is the process of receiving a one-way stream originating from the server or from another client connected to the server. A subscribed stream can receive any media source or ActionScript object of any type.

The following script will attach any media being sent on the subscribe_ns stream to an embedded video object on the Flash stage with the name my_video:

my_video.attachVideo(subscibe_ns);

At this point, the stream has been associated, but has not been established with the server. Its direction has not yet been declared. To establish the connection and identify the connection as a subscription, the play() method is called. To connect to a live or recorded stream with the name myStream, use the following code:

ns.play("myStream", -2, -1, false);
// Start the stream, "myStream",
// (-2) if the live source is not available,
// look for a recorded stream of the same name.
// (-1)Play until the stream is over

The play method has a series of parameters that control the starting position (for nonlive streams) and the length of play, as well as a Boolean value that will clear a play list (more on that shortly). For full details on the parameters of the play method, refer to Appendix B.

At this point, the Flash player will start receiving the stream. If you review the App Inspector, you will see an entry in the Streams tab showing your subscription stream. You will also see clients who are subscribing to it.

The subscribed stream will begin to play once the NetStream buffer has been filled with enough stream to start playing. The buffer is a memory allocation that will temporarily store incoming stream data before it is played back. This is done to ensure you do not experience drop outs due to network congestion. Think of a portable CD player with an anti-skip feature. This allocates a bit of memory that will preload your CD music before you start hearing it. If the CD skips, it will start playing from memory. The buffer is the same idea, except instead of avoiding skips, it avoids network congestion.

The default buffer size is 2 seconds. You can change this using the setBufferTime() method.

NetStream PlayLists

Play lists on the client operate exactly the same as PlayLists on the server. You can stack play commands to create a sequence of video using multiple stream sources. You can also use multiple play commands to jump back and forth on a single prerecorded Flash video, in essence creating a dynamic edit decision list (EDL). You could even create a solution that will give your user the ability to edit and play back the sequence without touching the original source.

You can force a play command to override a play list by setting the last parameter to true. This will flush the play list.

NetStream Messaging

Earlier in this chapter, you learned that you can send ActionScript objects across the NetStream object. This is similar to calling a method over the NetConnection object; however, the principle difference is that NetStream is one-way. Methods invoked over this object cannot return anything to the caller. Messaging over NetStream is called broadcasting a message. It is achieved by invoking a method defined within the NetStream object on the client using the NetStream.send() method.

Consider this example: During a video broadcast, the user publishing the stream wants to illustrate a point by having each subscriber go to a specific web page. What if the publisher could send the URI of the web page through the stream and automatically open a web browser and have each computer that is subscribed go to that web page? That is a perfect example of what you can do with NetStream messaging.

On each client would be a function defined in the subscription NetStream object. This function would receive one parameter, the URI, and pass it to the getURL() function, similar to:

subscribe_ns.openBrowser = function(URI){
getURL(URI,"_blank");
}

The Flash stage of the publisher has a text input box with the instance name URItoSend_txt on the stage to allow the entry of any web site URI. When the user clicks a PushButton, it invokes a Click Handler that will call the method, openBrowser, passing the URI to each client subscribed to the stream. Here's the example code:

// Assign a the Click Handler to the PushButton, "submit_pb"
submit_pb.setClickHandler("broadcastURI");

// The Function invoked when the pushButton is clicked.
broadcastURI = function () {
      publish_ns.send("openBrowser", URItoSend_txt.text);
};

The .send() function calls a method on each subscriber named openBrowser and passes it the value of the text input field. As you saw earlier, this method will invoke the getURL() method on each client and open the link in a new web browser.

NetStream onStatus Event

The NetStream object also has an onStatus event that will be sent a notification each time the status of the stream (publish or subscribe) changes. There are a lot of Information objects associated with NetStream. They are broken down in to errors, warning, and noncritical status updates relaying information about the buffer, subscription (Play), publish, recoding, and seeking. A full listing of every NetStream Information object is available in Appendix C.

For full details of the NetStream object, refer to Appendix B.You should also review the SSAS Stream object in Appendix A,"Server-Side Objects Quick Reference." Appendix E contains some quick reference scripts that you can use to quickly create publishing and subscription streams with ActionScript.

RecordSet Object (Flash Remoting MX)

The RecordSet object is a sophisticated array of ActionScript objects that operates as a standard database query result set. The principle origin of the RecordSet object was to allow a Flash Remoting MX server to convert a standard Query Result Set into something that the Flash player could understand. This is where AMF comes into the picture. Flash Remoting MX allows application servers to respond to remote method requests and return their unique data objects to the Flash Remoting MX interpreter (AMF). AMF converts the data objects into normal ActionScript variable types. In the case of a Query Result Set, Flash traditionally had no object that could handle database columns and rows natively.

Macromedia introduced the RecordSet object with Flash Remoting MX to allow AMF to format a Query Result Set into something Flash could understand. The RecordSet is a complex associative array, with a series of query-like methods and properties. These objects allow ActionScript to interact with the RecordSet with traditional query-like methods, such as getColumnNames and referencing data by row number and column name.

RecordSet can be used with or without Flash Remoting MX. The object itself is a series of methods and properties with a prebuilt data management model. When the object's class is included, RecordSet becomes a standard ActionScript object that can be sent to a method or can occupy a slot on a SharedObject. The server-side and client-side RecordSet objects are identical. On both platforms, you must manually load the RecordSet Libraries to begin using them.

To load the RecordSet Libraries in Flash MX, add the following line at the beginning of your ActionScript:

#include "NetServices.as"

This Flash ActionScript file adds the NetServices and the RecordSet classes to your Flash movie.

The script in Listing 12.1 demonstrates how you can use the RecordSet object and its methods to quickly populate a RecordSet without using Flash Remoting MX. Normally, a RecordSet object is created by a service method returning a database result from the application server. For those of you familiar with handling databases, this is a great technique to work with structured data in a way that you might be familiar with.

Listing 12.1 Sample Usage of the RecordSet Object
my_rs = new RecordSet(["fname", "lname", "email", "userName", "Password"]);

// INSERT some data (3 rows) to the RecordSet
my_rs.addItem({fname:"Kevin", lname:"Towes", email:"ktowes@pnm.ca", userName:"ktowes",
  Password:"tin"});
my_rs.addItem({fname:"Kary", lname:"Livsey", email:"karyh@skiForLife.com", userName:
  "kary", Password:"river"});
my_rs.addItem({fname:"Scott", lname:"Hepworth", email:"scotty@paddleMyBoat.com", userName:
  "scott", Password:"fox"});

// ** UPDATE (replace) a column value in record 1
my_rs.setField(1, lname, "Hepworth");

// ** SORT The Data by last Name
my_rs.sortItemsBy(lname,"desc");

// OUTPUT some fields:
trace("your name is: "+my_rs.getItemAt(2).fname);

Compare the addItem() method to a SQL Insert command used to add data into a database. In ActionScript the syntax is:

my_rs.addItem({fname:"Kevin", lname:"Towes", email:"ktowes@pnm.ca", userName:"ktowes",
  Password:"tin"});

The SQL Insert syntax is:

Insert into my_table (fname,lname,email,username,password)
VALUES('Kevin', 'Towes', 'ktowes@pnm.ca', 'ktowes','tin');

As you can see, the same amount of code is required. Now, compare the update methods. In ActionScript, this is achieved with the setField() method:

my_rs.setField(1, lname, "Hepworth");

In SQL, the UPDATE command is used:

UPDATE my_table SET lname = 'Hepworth' WHERE ID=1;

For full details of the RecordSet object, refer to RecordSet in Appendix B.Also refer to Chapter 14 for detailed examples and interacting with a database.

SharedObject

The SharedObject is a programming model to share data between Flash players and servers in a persistent or temporary fashion. The SharedObject, in concept, is identical to the SSAS SharedObject, except in its implementation. For a real understanding of the SharedObject, refer to Chapter 11, "Server-Side ActionScript," and Chapter 8, "STEP 8: Collaboration with SharedObject()."

Let's start by detailing the different implementations of SharedObjects in Flash versus the Flash Communication Server. There are two major differences between the two. Flash ActionScript has two flavors of SharedObject: the Local and the Remote.

Local SharedObject

The local SharedObject is similar to an HTML cookie. It is a file that is saved to the client's hard disk. It is persistent when the user closes the Flash movie, and can be accessed when the Flash movie is reopened. The local SharedObject is useful for storing specific values that may affect the Flash movie, such as the frame number the player was displaying before shutdown. When a user opens the Flash movie, the state of the Flash movie would be maintained. This could also be used to transfer data from a Remote SharedObject, so that if the Flash movie became disconnected from the server, the user could sustain some operations, such as interacting with an address book.

Like the SSAS implementation of SharedObject, the local SharedObject writes its SO data to the hard disk on two occasions: when the movie is shut down and when the Flush command is invoked. Here is a simple implementation of the local SharedObject.

lcl_so.getLocal("myLocalSharedObject");

// Write a property to the Local SharedObject
lcl_so.test = " kevin";

// Read a property from a Local SharedObject
var my_var = lcl_so.test;

// Trace the data
trace(" Local SharedObject Read Test: "+my_var);
trace("LocalSize: "+lcl_so.getSize());

Local SharedObjects do not require the Flash Communication Server to operate, as the Remote SharedObject does.

Remote SharedObject

The remote SharedObject is similar to the local SharedObject. It is not stored on the local computer, however, and must be used with the Flash Communication Server. The key operational difference is the synchronization that occurs between each connected client and the server. The synchronization process is identical to the SSAS implementation. You can review the synchronization processes in Chapter 11. There is also a great onSync ActionScript template in Appendix E.

Let's review the differences in implementing SharedObjects on the Flash client and within SSAS. Table 12.1 demonstrates the ActionScript and feature differences.

Table 12.1. Differences Between the Client- and Server-Side Implementations of SharedObject.

Command

Flash ActionScript

Server-Side ActionScript

Calling the SharedObject

so =
SharedObject.getRemote();
so.connect();

so = SharedObject.get()

Writing a data property (SLOT)

so.data.mySlot =
value; or so.data
[mySlot] = value

so.setProperty
("mySlot","value");

Reading a data property

my_var = so.data.mySlot;
or my_var = so.data
(mySlot);

my_var = getProperty
["mySlot"]

Synchronization

Same implementation

Same implementation

Status Information Objects

Same messages

Same Messages

Monitoring changes

A frequency value set

;
using so.setFPS()

Changes are instantaneous

Locking

No (only with local SharedObjects)

Yes

Sending/receiving broadcast messages

Yes: so.Send(); (same implementation)

Yes: so.Send(); (same implementation)

Flushing

No (only with local SharedObjects)

Yes

Clearing and purging

No

Yes

Retrieve size

Yes

Yes

Proxy SharedObjects

No

Yes

As you can see, the Server has more control over the SharedObject. This is because the actual object exists within the local resources of the server. The location offers additional functionality to the server.

For full details of the SharedObject implementations on the Client, refer to Appendix B.Also refer to Chapter 8, "STEP 8: Collaboration with SharedObject ()," for detailed examples.

System Object

The System object is used to return information about the Flash player environment. There two principle methods that can be used with the object: capabilities(), which returns the resources available to the Flash player, and showSettings(), which invokes the Flash player's Security Settings panel.

System Capabilities

This object was available in the release of Flash MX and is documented in the product manual and the online dictionaries. You should be aware of this method and its properties when developing Flash Communication Server applications. Invoking the capabilities function is like accessing raw data. The returned data must be parsed by you. The string below is a sample of the capabilities return variable:

"A=t&MP3=f&AE=gsm&VE=h11&ACC=f&V=WIN%206%2C0%2C0%2C129&M=Macromedia%WINDOWS&R=400x
  200&DP=72&COL=color&AR=1.0&OS=WINDOWS%2000&L=en-US"

As you can see, it's a URL-encoded name and value pair string. An easier way to interact with this data is using the System.capabilities properties. For example, to return if the player has MP3 abilities, you could simply use the following string:

System.capabilities.hasMP3;

This property will return a Boolean value. You may be asking, "Aren't all Flash players the same?" No, they are not. Flash players have different support features and are even coded differently for each device, browser, and operating system. Flash Player 6 on a mobile device has different properties than the player installed on a PC running in Netscape. The most obvious difference is the screen size and dots per inch. Using the System object you can dynamically control what is delivered to the device, based on the capabilities method.

For full details of the System object capabilities, refer to Appendix B.

System Settings Panel

The System object contains another method that was not documented in the manuals or the online dictionaries. The method System.showSettings() lets you control the Flash player's Settings panel. The Settings panel lets the user customize settings to local resources, such as access to the camera, microphone, or hard disk and the devices the Flash player uses for microphone and camera input. Figure 12.5 displays the four panels available.

Figure 12.5. The Settings panel contains four screens.

You can use the System.showSettings(whichPanel) method to force a panel to appear. A common use of this is when the user denies access to the microphone or camera and your application requires these devices to operate. You can message the user, informing him of the requirement, and force the Settings panel to reappear. Each panel is associated with a number (0–3). 0 references the first tab, and 3 references the last tab (camera). If you do not supply which panel to open, the panel that was displayed last will appear.

The Settings panel can also be accessed by the user right-clicking (Cmd-click on the Mac) anywhere in the Flash player.

Video Object

The Video object is a placeholder on the Flash stage that handles video sources from imported or linked video assets, the Camera object, and NetStream. This is a critical element to decompress and display incoming streams from the Flash Communication Server. The Video object can't really do much on its own. Its key feature is the control it has over the internal (Sorenson Spark) decompressor (codec). Most of the operations on actual playback are handled by the NetStream object. If you are using the Video object to handle imported video (without Flash Communication Server), then simple Timeline commands are used to control the playback.

For full details of the Video object's compressor controls and monitoring properties, refer to Appendix B.Also refer to Chapter 7 for detailed examples about using the Video object with NetStream.


The Macromedia Flash Communication UI Components

The Flash Communication UI components (Figure 12.6) were designed by Macromedia to offer solutions to build communication applications very quickly and, in most cases, without ActionScript. They are available from the Components panel (Ctrl+F7). Macromedia will be updating the Communication UI component library periodically. To acquire the most recent library, visit: http://www.macromedia.com/go/flashcom/.

Figure 12.6. The Flash Communication UI components can be downloaded from Macromedia.com (http://www.macromedia.com/go/flashcom/).

As demonstrated in Chapters 1 through 10, you can achieve some great results with these Communication components. However, as you have learned, you will reach a point where your requirements are outside the abilities of the UI components. When you reach that threshold, there are two options: You could "roll your own" solution or you could access the UI components' ActionScript objects and build on top of the foundation provided by the components.

Communication Components ActionScript Objects

Each Flash Communication UI component has an associated ActionScript object. If you choose not to use the SimpleConnect UI component, then you must use the ActionScript methods to connect components to the NetConnection object.

It is imperative that each UI component placed on the stage has an instance name. This is how you will access it using ActionScript. Assign the instance name in the Properties panel (see Figure 12.7) when the component is selected on the Flash stage. Flash UI components do not have ActionScript code hinting, but are actually just MovieClips on the stage. Use the suffix _mc to enable MovieClip code hinting in the ActionScript Editor.

Figure 12.7. You must ensure that each component has an instance name in the Properties panel before you can control it with ActionScript.

Only ActionScript classes associated with components available on your Flash stage will be accessible. For example, you cannot use methods in the Chat component if you are not using it.

The Flash UI components are built on top of the Communication objects in Flash MX. They are often confused as a standard part of the Communication Server. They are not. Classes are available only when the UI component exists in the application. SSAS classes are available for all UI components when using the load("components.asc") command in the main.asc file.

Each component (except simpleConnect) has at least two methods: .connect() and .close(). These methods are responsible for associating a UI component to the RTMP connection.

Most components also use the method .setUsername(). This method is required by components that handle user-specific operations, such as the Chat or PeopleList components. .setUsername() is normally invoked automatically with the .connect() method, but you can invoke it separately to change the username or enter the user into Lurker mode.

Lurker Mode

Lurker mode is a mode that is specific to the operation of some Flash Communication Components. Setting a user in this mode is the process of "hiding" them. They will not be able to publish streams or interact in a chat session. When in this mode, the client's username is not accessible.

If you use simpleConnect with the UI components, a user can enter Lurker mode by connecting with an empty username. If you are connecting the user with ActionScript, each UI component must be set to Lurker mode manually using their .setUsername() method. The following script will set the PeopleList, Chat, and AVPresence components to Lurker mode:

peopleList_mc.setUserName();
chat_mc.setUserName();
avPresence_mc.setUserName();

Additional Component Functionality

Communication components may have additional properties beyond.connect(), .close(), and .setUsername(). For a detailed list of the methods, properties, and events available in each component class, refer to Appendix D,"Macromedia Flash UI Component Object Quick Reference."

Extending the UI Component Class

When you explore the Communication UI component library, be sure to double-click the first asset. Frame 1 of the Actions layer contains the prototype of the Component object. You can overwrite these prototypes (extend the class) in your ActionScript. It is not recommended that you tamper with scripts in this frame, but you can certainly use them as a foundation to extend the functionality of the UI component by adding new methods and properties. For example, you could write a method that would let you set a ClickHandler property for the PeopleList component. This would let you use the PeopleList to trigger ActionScript events instead of it being a viewer component.

This process was demonstrated in Chapter 10, "STEP 10: Lobby Applications." In that chapter, the RoomList component's prototype method, joinRoom, was overwritten to extend the native functionality of the component.

Skinning the Components

Skinning is the way you customize how the Communication UI components look. To maintain a consistent look and feel to your users, you must consider how these components will fit into a custom layout. Remember, presentation is key, and now that Flash Communication Server takes care of the plumbing for you, more attention can be applied to the visual interaction of interface elements. The default Communication UI components are actually reskinned versions of the components shipped with Flash MX. The PushButton in the Chat window is the same button found in the Flash UI Components panel—it just looks different.

When a Communication UI component is dragged to the Flash stage, the assets it requires are copied into the Library folder called FlashCom UI components. Figure 12.8 shows the assets of the Chat component.

Figure 12.8. Flash Communication component assets will display in the Library in the Communication Components folder.

Flash UI components are built within the framework way as the traditional UI components. That means, if you are familiar with changing the skin of a UI component, this will be the same process.

This process is well documented in several books, including the Flash MX manual and Jody Keating's Inside Flash MX (New Riders Publishing).


Code Hinting

The Flash MX ActionScript Editor supports code hinting and code completion to help you script your applications. Table 12.2 provides a complete list of the Communication object suffixes that will automatically invoke the code hint and code completion tools. As a convenience, the entire scope of ActionScript suffixes are listed in the table.

These suffixes are not just useful for code hinting; use them for all your code to help self-document it. Understanding what type of data is stored within the variable will help you debug any application you create. Suffixes are added to the end of ActionScript variable names. For example, consider a variable name that might be used for a RecordSet object. The variable name myDatabaseData does not invoke code hints in the ActionScript Editor, but myDatabaseData_rs invokes the code hint for the object in both Flash MX and Dreamweaver MX (if you used Dreamweaver to edit Flash or server-side ActionScript).

Table 12.2. ActionScript Suffixes to Enable Code Hints

COMMUNICATION OBJECT CODE HINT SUFFIXES

Object Type

Suffix String

Var Example

Suffix String

Camera

_cam

NetServices

NetServices

Video

_video

NetStream

_ns

LocalConnection

_lc

RecordSet

_rs

Microphone

_mic

SharedObject

_so or SharedObject

NetConnection

_nc or _conn

REGULAR ACTIONSCRIPT CODE HINT SUFFIXES

Object Type

Suffix String

Var Example

Suffix String

MovieClip /

_mc

Date Object

_date

Communication UI component

Array

_array

Sound Object

_sound

String

_str

XML Object

_xml

Button

_btn

XML Socket Object

_xmlsocket

Text field (including input)

_txt

Color Object

_color

FLASH UI COMPONENTS CODE HINT SUFFIXES_CH

Object Type

Suffix String

Var Example

Suffix String

CheckBox Object

_ch

Scrollbar Object

_sb

PushButton Object

_pb

Checkbox Object

_cb

RadioButton Object

_rb

Scroll Pane Object

_sp

ListBox Object

_lb

globalStyleFormat

globalStyleFormat


Debugging Techniques

Bugs are present in most applications in the development process. Knowing the landscape of tools that are available to you will help you reduce, and hopefully eliminate, errors or unpredicted events from your final product. This section introduces you to some of the tools available and mentions specific techniques for debugging communication applications. Traditional ActionScript debugging techniques are covered in the Flash MX manual, and such other resources as Inside Flash MX and Phillip Kerman's ActionScripting in Flash MX (New Riders Publishing).

The ActionScript Interpreter

Unlike Dreamweaver MX, Flash MX does have an ActionScript interpreter built in. This allows you to test and automatically format your code before publishing your movie. Testing your ActionScript before you publish will save you a lot of time. To invoke the interpreter to test your code, click the ActionScript panel (F9) and click the check mark at the top of the panel (see Figure 12.9), or you can press Ctrl+T.

Figure 12.9. To test your ActionScript, click the check mark in the ActionScript panel. To format your code, click the paragraph icon.

If your code has errors, a dialog box appears in Flash MX informing you of an error (see Figure 12.10).

Figure 12.10. Flash MX informs you if your code has a syntactical error.

Flash provides an error report in its Output window (F2) that details exactly where the error occurred—complete with the Scene, Layer, and Frame number. Following the location information, Flash tries to interpret the problem and the ActionScript that caused the problem. For example, in Figure 12.11 you can see that a closed bracket, ), is missing from the nc.connect string. Once you correct the problem, the interpreter returns a success message with a happy bing, as shown in Figure 12.12.

Figure 12.11. The Output window displays full error details.

Figure 12.12. Flash MX informs you if your code is error free.

Each time you add a new piece of code, you should test your code by pressing Ctrl+T. This will make it easier to track errors.

Three other tools help you debug your ActionScript. The Output window monitors any trace activity in your script, the ActionScript Debugger lets you step through your movie so you can track the values of objects and properties, and the new NetConnection Debugger allows you to watch communication between the Flash Communication Server or a Flash Remoting MX server.

Trace Actions

Trace Actions are the simplest and, in most cases, your best form of monitoring when functions run or when a Communication object's status changes. The extreme trace in Figure 12.13 shows status activity for NetConnection and NetStream, trace activity for functions that were run and messages from the server. The trace in Figure 12.13 is the output from the onStatus ActionScript template in Appendix E.It is a great tool to help you watch status changes and track where errors are occurring.

Figure 12.13. Trace Actions let you monitor in real time what is happening in your code. They are displayed in the Flash MX Output window.

Debug Movie

A great improvement of earlier tools, the Flash MX Debugger is the standard debugger used for all ActionScript (communication or not). If you are new to Flash MX, you will see that this is a comprehensive tool that lets you watch property values, seeing the property tree with their values. Figure 12.14 shows the property trees of an array (infoMessage_array), a RecordSet (my_rs), a NetConnection (nc), and a SharedObject (so).

Figure 12.14. The Flash MX Debugger lets you drill into object properties and values.

The Debugger is a big tool, but here are the highlights:

  • Visually access complex movie and object structures in a tree-type display.

  • Change or examine property values of any ActionScript type.

  • Track variables.

  • Monitor the execution of specific functions using the Call Stack window. You can also drill down into the function or ignore it completely.

  • Set watchers and breakpoints in the code to actually stop the code from executing and provide a snapshot of what is going on.

The Flash MX Debugger can be used to closely monitor what is happening in your Flash ActionScript, but it is just one more piece in your arsenal. The Flash Communication Server added another debugging tool that you can use to monitor activity between server and client.

NetConnection Debugger

The NetConnection Debugger monitors AMF communication between client and server. You can use this tool to monitor exchanges between the client and the Flash Communication Server over RTMP and exchanges between the client and a Flash Remoting MX server over HTTP.

It is a watcher tool only; you cannot interact with the data, and you cannot control the server actions or interact with the functions like you can with the Flash MX Debugger. As you can see in Figure 12.15, this tool monitors all ActionScript communication over the NetConnection.

Figure 12.15. The NetConnection Debugger monitors all AMF traffic over NetConnection, RTMP, and Flash Remoting MX HTTP.

The figure example shows a function call from the client to the server over RTMP. If there were properties sent, they would be displayed here.

Filters allow you to track specific messages and even monitor SSAS trace activity. When used with Flash Remoting MX, the NetConnection Debugger can track the RecordSets being returned from an application server Remoting service. It's a great tool to help you monitor the communications.


Summary

As you have seen, you can be very successful with developing Communication Server applications without ActionScript. To get the full power of the technology, you will have to become familiar with the ActionScript objects and tools mentioned in this chapter and in Chapter 11. Appendixes B, C, and D contain details of every aspect of the Communication and Flash Remoting MX objects, Flash UI components, and a full directory of the onStatus information objects. For generic ActionScript templates, refer to Appendix E.The most important thing to remember is that Flash doesn't just do communications applications. Flash is also a great tool for skip intros, animation, and building some rich user interfaces.


Chapter 13. Accessing External Data

One of the most exciting features of Macromedia Flash MX (and Flash Player 6) was the introduction of Macromedia Flash Remoting MX. Also known as Remoting, this feature is what moved Flash to become an alternative for thin client computing. Flash Remoting MX allows you to connect the Flash player with an Application Server that can provide online services such as database access or sending email. Remoting does not have to be used with Macromedia Flash Communication Server MX; however, when you combine these two technologies, you can really do some interesting stuff. Some examples include the ability to take your database offline, work with it, and when you reconnect, Flash will automatically resynchronize itself registering any changes that you (or anyone) made. Another example is user notification or instant messaging. Let's say someone makes a change to the database. You could build an application that notifies every user that a change has been made. But you could also take it one step further and decide to lock database records or allow multiple people to interact with the database in real time.

This chapter will give you a basic overview of accessing a database using the Flash Communication Server with Flash Remoting MX. Because Flash Remoting MX can be used without the Flash Communication Server, you will also learn some distinct techniques for data distribution using the Flash Communication Server. It's a practical chapter, with a series of exercises to get you started. In the exercises, you will use Flash Remoting MX to authenticate a user logging into your system. You will also collect a database RecordSet and learn just one technique to distribute it among connected clients. Taking it one step further, because that is the theme of this book, you will build an application that can be used with devices that can be disconnected. Take your database on the road with you! Hold on—this one's gonna be a great ride!


Macromedia Flash Remoting MX

Flash Remoting MX can interface with most Web Services or interact with Application Servers that are supported by Macromedia. The technology uses a format called Action Message Format (AMF). This format is unique in that it transfers binary data between the Application Server's Flash Gateway and either the Flash player or the Flash Communication Server. Traditionally, Flash developers were pinned to the floor with XML. I'm not saying that XML is bad; in fact, it's quite the opposite. XML is a great, user-friendly form to transmit data. Being so user-friendly, it carries some overhead. Parsing XML in Flash is complicated and relatively slow. Macromedia, with the release of Flash Player 6, dramatically improved the XML parsing engine in Flash; however, it really doesn't compare to the speed both in development and at runtime of Flash Remoting MX.

Connecting with Application Servers is now a very natural event for both the Flash player and the Flash Communication Server. Application Servers are intermediary technology that can expose server resources to public interfaces such as HTML, Flash, or external servers. Traditionally, the Application Server was used to expose database information or as a framework to manage content via a web browser or some Internet user interface. Flash developers learned very quickly (in Flash 4.0) that you could use an Application Server to deliver content to the Flash player using the loadVariables() method. In Flash 5.0, Macromedia extended this functionality with the XML object. Both of these operations involved heavy code and development to assemble, transport, and convert into ActionScript objects. Flash Remoting MX was introduced in Flash MX as a way to remove the preparation stage that was required to transfer database data or add advanced server resources to the Flash movies. Server resources could include databases, email servers, LDAP servers, and even file systems.

Using Flash Remoting MX allows the developer to leverage these servers and development teams familiar with the technology to expose Flash to standard application programming interfaces (APIs) to be consumed by the Flash player or the Flash Communication Server or even other Application Servers and resources. By calling a simple public (or remote) method, Flash can receive ActionScript objects such as a special RecordSet object, which is a sophisticated array of objects acting like a standard query object.

There are two types of commercially available Application Servers on the market today. It is the battle between Microsoft .NET and Java (Java 2 Enterprise Edition) Frameworks. Flash Remoting MX is available natively on Macromedia J2EE Server products, JRUN 4, and Macromedia ColdFusion MX. It is also available as an add-on for any J2EE server such as SunONE, IBM WebSphere, or BEA WebLogic. Microsoft.NET is also supported if you use ASP.NET, C#.NET, or VisualBasic.NET. If you are not using the Macromedia Server products, Flash Remoting MX components are available for purchase on the Macromedia web site at http://www.Macromedia.com/go/flashremoting/.

Note

We don't have enough space in this book to go through each Application Server, so we'll use Macromedia ColdFusion MX because it is easy to understand and has native support for Flash Remoting MX. Keep in mind as you read that everything we are doing in ColdFusion can be done in any language that supports Flash Remoting MX (.NET or J2EE).

Working with the NetServices Object

The NetServices object is an ActionScript object with methods and properties used to connect with Application Servers and Web Services. The object communicates with Remoting-enabled Application Servers using Macromedia's home-grown AMF language over HTTP. Instantiating the object will give your application access to public (.NET) or Remote (ColdFusion) methods that you can create on your Application Server. It also gives you easy access to any methods embedded within a Web Service. NetServices takes care of all data transportation and transformation, and returns standard ActionScript objects that are ready to use with no additional handling required.

The NetServices object is available on both the Flash Communication Server and within Flash MX. You can choose to directly access an Application Server with the Flash player or through Flash Communication Server. For a complete list of methods available with NetServices, refer to Appendix B,"Macromedia Flash ActionScript Objects Quick Reference."


NetServices in Macromedia Flash MX

To use Flash Remoting MX within Flash MX, you must first download the Flash Remoting MX components from www.macromedia.com/go/flashremoting. This download extends Flash MX with a new Remoting ActionScript library (available in the ActionScript panel) and installs the NetServices.as class file. Included with the NetServices library are also the RecordSet, NetDebug, and DataGlue classes. RecordSet will be discussed later in this chapter. To include the NetServices class into Flash MX, you need this line of code at the beginning of your ActionScript:

#include "NetServices.as"


NetServices on the Macromedia Flash Communication Server

To enable NetServices on the Flash Communication Server, you must load the NetServices.asc ActionScript file. Loading this file makes the NetServices and RecordSet libraries available to the server. Before you can connect with Remoting-enabled Application Servers using Flash Remoting MX, the following script must be placed in the main.asc file:

load("NetServices.asc");

Unlike Flash MX, the Flash Communication Server does not require the Flash Remoting MX download from Macromedia.com.

RecordSet Object

The RecordSet object is packaged with NetServices and is available to both Flash MX and Flash Communication Server. A RecordSet is an ActionScript object that contains database columns (or fields) and rows (or records). Each row contains the values for each column that can be accessed by defining the row number and the column name. For example, to access the first name of a user that was returned in the sixth row of a database query, you would use one of the following:

var myVariable = myDB_rs.items[rowNumber].columnName;

Or

var myVariable = myDB_rs.items[5].firstName;

If you are familiar with handling RecordSets from a database, or Application Server, you should be aware that Row #1 in Flash is referenced by the index 0, not 1. A total record count of 10 would have a maximum index of 9.

The RecordSet object includes a series of methods that you can use to interact with your database RecordSet. It has been built to simulate traditional methods used when handling RecordSets. Handling data returned from a database is much easier and manageable with this object.

For a complete list of methods available with NetServices, refer to Appendix B,"Macromedia Flash ActionScript Objects Quick Reference."

Note

The RecordSet object is also available for Flash MX. If you place a RecordSet object within a Remote SharedObject as a slot of the data property, the Recordset will become available to all clients connected to the SharedObject. When accessing the RecordSet slot in Flash MX, you can interact with the data just as easily as you can in Flash Communication Server.

To enable the RecordSet methods, you must load the NetServices class.

To enable the RecordSet methods in Flash MX, you must have the Flash Remoting MX components installed, and then include the following script at the start of your Flash movie:

#include "NetServices.as"

To enable the RecordSet methods on Flash Communication Server MX, you must include the following script in your main.asc file:

load("NetServices.asc");

This was a brief overview of the Flash Remoting MX component. The exercises within this chapter will step you through the process of using Flash Remoting MX with the Flash Communication Server to authenticate a user against a database.


Project: Using Remoting to Authenticate a User

Before you begin these exercises, you will need an Application Server like ColdFusion MX and a database like Microsoft Access, SQL Server, or SyBase. You can download a trial version of ColdFusion MX from http://www.Macromedia.com/go/coldfusionmx/. We will create and connect the database in this exercise using Microsoft Access 2000. Flash Remoting MX uses the standard HTTP protocol, so you will need a web server installed. For this exercise, Microsoft IIS5.0 web server is our server of choice. You are free to use other servers, including the stand-alone web server included with ColdFusion MX.

The first exercise has broad implications, but we are going to simplify it quite a bit. Remember that array of objects we used back in Chapter 11, "Server-Side ActionScript (SSAS)"? That example was demonstrating the Application object in SSAS using Application.onAppStart to define an array of user objects. You used that array as an authentication challenge when the user logged in. You matched a username and a password with the object properties in the array.

That example can be useful in a simple application that does not require user maintenance. It is also a bad technique to use because you are placing content (user information) in line with the code (ActionScript). A better technique is to use a database or an LDAP server to store user information. You could build another interface to manage the user information, without recompiling the application each time you want to make a change.

This project will step you through four exercises that will result in a fully functional application that will authenticate against a database. Here's an overview of the exercises:

  • Exercise 13.1: Setting Up the Database

  • Exercise 13.2: Creating the Database Call

  • Exercise 13.3: Consuming the CFC as a Web Service in Flash Communication Server

  • Exercise 13.4: Calling Flash Communication Server and Establishing a Connection Using Flash MX

Let's jump in with our first exercise to construct the database.

Exercise 13.1: Using Remoting to Authenticate a User

Assuming that you have ColdFusion MX installed and running, this first exercise will walk you through building a simple database using Microsoft Access. You can use most common database technologies supported by ColdFusion MX. Follow these steps to construct your database:

  1. Create a folder in the ColdFusion MX server's default web directory. Call the folder myFlashComService. This folder name is important and will be referenced later on in this exercise.

  2. Open Microsoft Access.

  3. Create a blank Access database with the name myFlashComDb.mdb (see Figure 13.1). Save the database file in the folder you just created, or a folder accessible by the ColdFusion Server.

    Figure 13.1. When MS Access opens, you will be prompted. Select Blank Access Database. You can also access this screen by selecting File, New in the MS Access Command menu.

  4. Build a database table using the Create Table in Design View feature (see Figure 13.2).

    Figure 13.2. Add tables to the database using the Design View Wizard.

  5. Create a series of fields in the database. The field list should include the following (see Figure 13.3):

    Field Name

    Data Type

    UserID

    AutoNumber (key)

    fname

    Text

    lname

    Text

    login

    Text

    password

    Text

    emailAddr

    Text

    phoneNum

    Text

    streetAddr

    Text

    Figure 13.3. Your field list should look like this. Don't forget to change the Allow Zero Length property to No.

  6. Assign the UserID as the key, or unique identifier. You can do this by selecting the field and clicking the Key icon in the toolbar.

  7. Change the value of Allow Zero Length to No for every field.

  8. Close the table and save it as Users (see Figure 13.4). Note that this table name will be used at a later point in this exercise, so if you do not name the table Users, remember what name you gave it.

    Figure 13.4. Save your table as Users. This is referenced later, so remember the name you choose.

  9. Populate the table with some values (see Figure 13.5).

    Figure 13.5. Populate your Users table with some data. Remember some of the logins/passwords.

  10. Save and close MS Access. Your database is complete and ready to go!

Now, connect the database to your ColdFusion MX server using the Data Sources window:

  1. Open the ColdFusion Administrator and Login.

  2. Click the Data Sources link in the Administrator menu.

  3. Add a new datasource: Enter myFlashComDb in the Data Source Name field and select the driver Microsoft Access, and then click Add.

  4. Browse the server for the database file you just created (see Figure 13.6).

    Figure 13.6. Connect the database to a ColdFusion MX data source using the ColdFusion MX Administrator.

  5. Click Submit and ColdFusion will verify the database. If you get an error, click the new data source name in the list and confirm that you have referenced the correct database file.

Now you are ready to rock and roll! We will use this database for other examples in this chapter.

Exercise 13.2: Build the Macromedia ColdFusion Script

With the database connected and ColdFusion all set up, you are ready to build the ColdFusion script. This script will expose a method returning a simple Boolean—true or false value—to the Communication Server. This method will require two parameters—can you guess which two? That's right, login and password. Each parameter will be a string. First, on to the ColdFusion:

  1. Create a new folder in the default web server called myFlashComService.

  2. Create a ColdFusion Component (CFC) file called login_service.cfc in the myFlashComService folder. (Macromedia Dreamweaver MX users can use the Create ColdFusion Component Wizard by selecting File, New, Dynamic Page, ColdFusion Component.) This creates a new CFC template.

  3. Open the login_service.cfc file in your favorite HTML editor. Dreamweaver MX has some excellent helper applications to build the ColdFusion components.

  4. Add the following script to define the CFC and the method that will be called by the Flash Communication Server:

    <cfcomponent>
            <cffunction name="authenticateUser" access="remote" returntype="boolean">

    The <cffunction> defines the name of the method you will call in Flash Communication Server. Dreamweaver MX users can use the Tag Editor to create the function (see Figure 13.7).

    Figure 13.7. The Dreamweaver MX Tag Editors offer GUIs for each ColdFusion tag. To access the GUI, enter the tag <cffunction>, and then right-click the tag and select Edit Tag.

  5. Create two arguments that will handle the data sent from Flash Communication Server:

    <cfargument name="login_str" type="string" required="true" default="null">
<cfargument name="password_str" type="string" required="true" default= "null">

    Dreamweaver MX users can use the Tag Editor to create the arguments.

Now, create the database call using ColdFusion's <cfquery> tag and some SQL:

  1. Open the database connection. In this tag, define the name of the query so you can access the results later. Also, define the datasource you assigned in the ColdFusion Administrator:

    <cfquery name="checkUser" datasource="myFlashComDb">

  2. Create the database SQL. This returns all the UserIDs of users with login and password equal to the arguments passed to the method from the Flash Communication Server:

    SELECT UserID
FROM Users
WHERE       login = '#arguments.login_str#' and
            password = '#arguments.password_str#'

    Tip

    You can also use a database function called Count to return the number of records from a database table. This function returns the number of rows that match the WHERE condition. This is a good idea if you have a lot of records in the database. In the preceding example, there would be x rows returned to the Application Server. In this example, there would only be one row returned with a single value:

    SELECT Count(UserID) as Total FROM...

Select Count(*) as Num from Users

  3. Close the <cfquery> tag:

    </cfquery>

  4. Use script to challenge the recordCount of the query. If one record was found, set the isLoginOK value to true. In this exercise, you will use CFScript, which is very similar to ActionScript in format. There are unique iterations of some operations, such as using IS or EQ versus == to match string values, as shown in the following code:

    <cfscript>
      if (checkUser.recordCount is 1) isLoginOK = true;  else isLoginOK = false;
</cfscript>

  5. Return the Boolean value to the Flash Communication Server:

    <cfreturn isLoginOK>

  6. Close the function and the component:

          </cffunction>
</cfcomponent>

That's it for the ColdFusion part of the application. You can run this CFC directly in a web browser. If everything is good, you will see a full description of the component including all methods with their return values:

http://localhost/myFlashComService/login_service.cfc

Tip

You can also reference this CFC as a standard WSDL Web Service by placing a ?wsdl parameter following the filename in the address bar of your browser:

http://localhost/myFlashComService/login_service.cfc?wsdl

Exercise 13.3: Consume the CFC as a Web Service in Flash Communication Server MX

Now that you have the ColdFusion Component set up and ready to go, you are ready to consume the CFC as a Web Service in the Flash Communication Server. We'll start at the server and then move to Flash MX to build the interface:

  1. Create a new application folder called myRemotingApp within the Flashcom Applications folder on the server.

  2. Create the main.asc file in the new myRemotingApp folder.

  3. Open the main.asc file in your development environment. Remember, you can edit server-side ActionScript (SSAS) scripts using a simple notepad-type editor like JavaScript Editor or Dreamweaver MX.

  4. Load the NetServices class files. This gives you access to the methods required to communicate with Application Services using Flash Remoting MX and the AMF format:

    // Load the NetServices Class Libraries
load("netservices.asc");

    Note

    This exercise does not use any Communication Server UI components, so there is no need to include them here. If your application uses the Communication Server UI components, you will have to load them:

    load("components.asc");

  5. Overwrite the Application.onConnection method, requesting two additional parameters: username and password:

    application.onConnect = function(clientObject, username, password) {

  6. Set the default gateway for NetServices. This is the name of your ColdFusion (or Remoting) server. Note that in ColdFusion, you must attach /flashservices/gateway to the URI to enable Flash Remoting MX. This is not a folder on the server. This reference points to the wwwroot of your default web server (if you are using Windows IIS):

    NetServices.setDefaultGatewayUrl("http://127.0.0.1/flashservices/gateway");

  7. Instantiate the gatewayConnection to a custom variable gatewayConnection:

    var gatewayConnection = NetServices.createGatewayConnection();

    Note

    If you want to use this connection anywhere else, you can set it as an application variable—for example, application.gatewayConnection. Or, because you are setting it within the application scope in onConnection, you can use this.gatewayConnection.

  8. Instantiate ColdFusion Component script or Web Service. The parameter within the getService method uses the dot syntax to define folders and files. In this example, the parameter is referencing the file login_service.cfc in the folder myFlashComService within the default web site:

          //  instantiate the service into a local variable
      var cf_service =
gatewayConnection.getService("myFlashComService.login_service", this);

    CFFunctions, or methods defined in the service (ColdFusion Component), can be called using the custom variable cf_service.

  9. Call the service as you would any regular ActionScript function, passing the required parameters—in this case, username and password:

    // call the server function, authenticateUser, passing the username and password
var callTheServer = cf_service.authenticateUser(username, password);

Note

You don't need to use the variable callTheServer, but you can use it to challenge if the function was run. If the function ran, the variable will contain the Boolean value true, and if it didn't run, it will contain the value false. This is helpful for debugging.

Just like NetConnection, or Stream, the service function returns either a Result or Status message to Flash Communication Server. The syntax is a bit different than you have seen. The name of the service function is suffixed with a _Result (remember, it's case sensitive and requires a capital R). If the function returns an error, it looks for the function with the same name, suffixed with a _Status. These next steps use this method, but you can also create a prototype handler for this, using an onStatus or onResult custom function:

  1. Create the _Result function with one parameter to handle the returned data (as scripted in the CFCs <cfreturn> tag):

    // handle the server response
this.authenticateUser_Result = function (result_boo) {

  2. Place a simple trace so you can monitor activity within the App Inspector:

    trace("The Server Responded, good for you! —> " + result_boo);

  3. Call a function to accept or reject the connection. The function you are calling will be scripted shortly. It will require two parameters: a Boolean value declaring an accept or reject and the clientObject. This script also contains the closing function bracket:

          // call the challengeConnection Function, which will accept/deny the connection
      challengeConnection(result_boo,clientObject);
};

  4. Create the error handler for the function using _Status. This handler also calls the challengeConnection function, passing a value of false to trigger a connect rejection. This is the last bit of code for the onConnect function, so include the closing function bracket:

          // handle any server errors
      this.authenticateUser_Status = function (status) {
            trace("Returned FAILED From the Server");
            challengeConnection(false,clientObject);
      };
// close the onConnect function
};

  5. Create the function challengeConnection to handle accepting or rejecting connections based on the server results. This function requires two parameters: a Boolean value and the clientObject:

    challengeConnection = function(isAuthenticated, clientObject) {

  6. Challenge the Boolean value passed from the caller (also known as the server) for a true or false value. With Boolean values, you are not required to place the sequence ==true or ==false. If the value is true, accept the connection; if not, reject it. This script also closes the challengeConnection function:

          if (isAuthenticated) {
            trace("You have entered the inner sanctum");
            application.acceptConnection(clientObject);
      } else {
            trace("Not today, my Friend...");
            application.rejectConnection(clientObject);
      }
}

That's it for the server(s). You can check your code in the App Inspector to make sure everything compiles correctly. Load the App Inspector, log in, and enter the following line into the App Inspector input field and click Load: myRemotingApp/myInstance. This compiles the application into the myInstance instance. If your code doesn't compile properly, you will see a Warning symbol show up on the App Inspector. Double-click it to determine the error.

A better way to accomplish this is to click View Detail with the new instance selected. This opens the Live Log panel. Click the Reload App button and the trace actions are displayed in the output window. This window also displays any compile errors with some details where the errors occurred. Figure 13.8 is an example of what your Trace window should look like.

Figure 13.8. The App Inspector is used as the SSAS Trace output window. When you click the Reload App button, your output should look like this.

Exercise 13.4: Call Flash Communication Server and Establish a Connection Using Macromedia Flash MX

This final exercise will move into Flash MX. To save time on this exercise, you will not build an interface. Our objective is to call Flash Communication Server and establish the connection. It's a real simple application, but it will build the foundation for you to construct secure applications:

  1. Create a new Flash movie called mySecureApp.fla and save it in your work folder, or on the Flash Communication Server, in the myRemotingApp folder.

  2. Open the ActionScript panel (F9).

  3. Instantiate the NetConnection object to the variable nc:

    nc = new NetConnection();

  4. Create a simple onStatus function for the NetConnection that lets you watch the connection either be rejected or connected:

    nc.onStatus = function(info) {
      trace("LEVEL: "+info.level+"  CODE: "+info.code);
};

  5. Connect the movie, passing a valid login and password to the Application.onConnect function:

    nc.connect("rtmp:/ myRemotingApp/myInstance", "tin", "can");

That's it! You're now ready to test your application. But before you do, understand what is going to happen. Your Flash MX output window will inform you if the connection was accepted or rejected. The App Inspector Live Log panel will output the trace actions you scripted in your main.asc file. Because you don't have an interface with this application, these are your only tools to determine if your connection was successful or not. Figures 13.9 and 13.10 show what a successful connection looks like when you test your movie (Ctrl+Enter).

Figure 13.9. The Flash MX output window showing the accepted connection.

Figure 13.10. The App Inspector Live Log panel showing the accepted connection.

When you have made a successful connection, try to log in with a bad username and password. Close the test movie and enter an INVALID username and password into the connect function. Then, test your movie again. Monitor the output window and the App Inspector. You should see output similar to what's shown in Figures 13.11 and 13.12.

Figure 13.11. The Flash MX output window showing the rejected connection.

Figure 13.12. The App Inspector Live Log window showing the rejected connection.

You will obviously need to extend this exercise to put it into proper use. The most common method would be to place two input text fields on your Flash stage, giving them instance names of login_txt and password_txt. Change your Connect string to the following:

nc.connect("rtmp:/ myRemotingApp/myInstance", login_txt.text, password_txt.text);

SSAS on Macromedia ColdFusion MX

ColdFusion MX also fully supports Flash MX ActionScript (on the server) to interact with a database. Using the file format .ASR, ColdFusion MX interprets the script as ActionScript. Unique ColdFusion objects are available, including a database query method. The entire ColdFusion Component that you created in the previous exercise could have been scripted like this within the login_service.asr file stored in the same folder:

function authenticateUser(login,password) {
      theSQL = "SELECT UserID FROM Users WHERE    login = '#arguments.loginstr#' and
  password = '#arguments.passwordstr#'";
      checkUser = CF.query({datasource:"myFlashComDb", sql: theSQL});
      if (checkUser.recordCount ==1) isLoginOK = true;  else isLoginOK = false;
      return isLoginOK
}


Summary

Flash Remoting MX is a very important feature to both Flash MX and the Flash Communication Server. If you are interested in learning more about Flash Remoting MX, review Inside Flash MX, published by New Riders Publishing, paying particular attention to the chapter on Flash Remoting MX. This is a fantastic chapter on the whole picture of Remoting, including a detailed explanation of Application Servers. There is also a workshop in the third part of this book that walks you through the steps of sharing database records using SharedObjects. It's a great workshop that really demonstrates the concepts of making your database portable in this world of mobile devices such as the Pocket PC.


Chapter 14. Server Administration

Macromedia Flash Communication Server MX is clearly an amazing piece of technology, but how does it compare with enterprise-level server applications? For a 1.0 release, Flash Communication Server stands up very well. It is truly scalable and secure, and it has a structure that stands up to the best, as you'll see.

This chapter provides a general walkthrough of the server administrator and how to expand the server. If you are an Internet service provider and want to offer shared hosting with Flash Communication Server, this chapter will be very important. Even if you are a developer who never plans to expand the server to multiple developers or tightly secure applications, you should review at least the section on the Application.xml file. This file allows you to override the server's general settings to manage bandwidth, streams, loading, and other low-level settings for particular applications. One great setting is the load-on-startup setting that will allow your application to create an instance whenever the server reboots.


The Server Structure

The Flash Communication Server is divided into four levels, as shown in Figure 14.1's Venn diagram. Each inner circle adopts the access model and resource limitations defined by the outer circle. Each inner circle also applies additional limitations on security and resources. The security and resources of the application (inner-most circle) are a culmination of the outer levels. The four levels are:

  • Server. A collection of adaptors configured with Server.xml. The server defines the computer resource limits available across all adaptors. It also defines the administrator user security.

  • Adaptor. A collection of virtual hosts configured with Adaptor.xml. The adaptor defines the server resources available to each virtual host plus the security restriction levels.

  • Virtual host. A collection of applications configured with Vhost.xml. The virtual host exists within the limitations set by the adaptor.

  • Application. A collection of server-side ActionScripts (ASC), Flash video (FLV), and Stored objects (FSO) files configured with Application.xml. All applications are subject to the limitations declared in the adaptor and virtual host configuration files.

Figure 14.1. The Server structure and the corresponding configuration files.

Up to this point you have only been interacting with the application. You can section off applications just like creating web servers in Windows IIS or domain entries in your DNS server. You can manage the bandwidth and user capacity for each "section," as well as manage ports and limits per adaptor.

These next sections will step you through the controls for each server level. Each level will address the physical location, user management, configuration, and security tips. At the end of the chapter, the exercises will step you through the process of creating and managing multiple adaptors and virtual hosts.

Note

An important security consideration for Flash Communication Server is that the RTMP protocol, although it is a binary format, does not support encryption. You can achieve encrypted communication when you use ticket-based authentication over a secure Flash Remoting MX connection on the Flash client. Because Flash Remoting MX can use the secure HTTPS protocol, it safe to transfer secure information.

A ticket-based system would engage the Flash player to request a "code" assigned by an application server through a secure Flash Remoting MX connection. That code would then be passed to Flash Communication Server using RTMP. Flash Communication Server would connect with the application server to validate the code. This technique is used between many systems to pass secure information from a secure environment to the public interface.


The Server

The Flash Communication Server is intended to be installed as a stand-alone server, in that it does not require a web server or application server to run. It does, however, require additional elements to make it function. Flash SWF movies are usually accessed through a web server. Databases and external server resources can be accessed though application servers. For development, the server should be installed with a web server already installed because this arrangement makes managing scripts and other application elements easier for developers. When a server is ready for public access, you should move application scripts away from the web server access, separating the SWF movies and the ASC, FLV, and FSO files.

Macromedia built the Communication Server server architecture with two things in mind: scalability and security. A model similar to the relationship of your network card and IP addresses or domain names is used. Communication Server employs adaptors and virtual hosts to isolate users and applications. This model is also used to provide domain-level restrictions and access control. The Communication Server has many internal security provisions for its operation and for accessing the applications that run within it. It is, however, the responsibility of the individual developer (you) to achieve security of your data and the integrity of the application.

The Server can connect and can accept connections to a number of components, including other Flash Communication Servers, application servers, web services, or Macromedia Flash 6 Players. Flash Communication Server applications can communicate with these resources in two ways:

  • Persistent connections between Communication Server server and Communication Server server or between Communication Server server and Flash player. The Real Time Messaging protocol (RTMP) is used. This is a clear text format that is not encrypted.

  • Nonpersistent connections between Communication Server server and application server or between Flash player and application server. Nonpersistent connections use a standard or encrypted HTTP(S) protocol.

Both RTMP and HTTP protocols use the Action Message Format (AMF) to transport ActionScript objects. AMF is available with most application servers (.NET and J2EE) that support Flash Remoting MX.

The server is a collection of adaptors, virtual hosts, and applications. A Flash Communication Server application might consist of streams, users, and SharedObjects. The Macromedia Flash MX authoring environment and Macromedia Dreamweaver MX are the integrated development environments (IDE) of choice. For Dreamweaver MX, however, you can substitute most JavaScript or simple text editors. You can develop Communication Server applications on either Macs or PCs, but the 1.0 server is available for Windows platforms only.

The server is installed with one adaptor and one virtual host. Defining new adaptors and new virtual hosts involves the management of folders and configuration XML files. Figure 14.2, displays the folder structure of the _defaultRoot_ adaptor, and its _defaultVHost_ virtual host. Each folder and configuration file will be discussed in detail later in the chapter.

Figure 14.2. The conf configuration folder located in the root of the Communication Server install path. This tree is the installed default.

Users

A server user assumes the role of system administrator. This user has the control to interact with and restart all aspects of the server including applications, virtual hosts, adaptors, and the entire server. The server user is sometimes referred to as the root user. You can have multiple root users on a server.

Root users are managed in one of two ways:

  • You can use the Administration Console to add, remove, or change a user's password.

  • You can edit the server configuration file. Passwords can be encrypted or unencrypted. This setting can be overridden in the Server.xml configuration file.

There is no advantage to using one way or the other.

Configuration: Server.xml

Located in the root of the conf folder, the Server.xml file controls registration of root users, adaptors, and virtual hosts. The Administration Console can manage users and will overwrite this file. You also use Server.xml when declaring new adaptors and virtual hosts. Below is an overview of a default Server.xml file. This XML description includes nodes that were not included in the original documentation of the Communication Server.

<Root>
   <Admin>
      <Server>

The <UserList> node then defines each user that has root-level access to the Administration Console and the Administration API:

   <UserList>
      <User name="admin">
            <Password encrypt="true">YWRtaW4=</Password>
            <Allow></Allow>
            <Deny></Deny>
            <Order>Deny,Allow</Order>
        </User>
   </UserList>
</Server>

The <Allow> and <Deny> nodes specify the IP addresses or domains from which the user can and cannot access the Administration Console. The <Order> node determines how the server processes the values declared within the <Allow> and <Deny> nodes. If Deny precedes Allow in the <Order> node, as the previous listing shows, access will not be granted from any host listed within the <Deny> node and is not listed in the <Allow> node. When the <Order> node is reversed (Allow, Deny), then the same user can access the Administration Consoles only if the host is listed within the <Allow> node.

In the next portion of the file, the <Adaptor> node defines each adaptor on the server. Adaptors contain virtual hosts that are defined within the <VirtualHost> node. You can set domain restrictions on each virtual host. Virtual host users are defined within the <User> node.

    <Adaptor name="_defaultRoot_">
       <VirtualHost name="_defaultVHost_">
          <User name="admin">
                <Password encrypt="true">YWRtaW4=</Password>
                <Allow></Allow>
                <Deny></Deny>
                <Order>Deny,Allow</Order>
            </User>
         </UserList>
       </VirtualHost>
     </Adaptor>
</Admin>

Finally, the <Server> node defines the serial numbers used and the port to access the Administration Console. The <ResourceLimits> node gives you some control over which resources the server can consume on the server. This node was not included in the original documentation for Flash Communication Server.

  <Server>
  <LicenseInfo>FSW100-XXXXX-XXXXX-XXXXX</LicenseInfo>
  <AdminServer>
    <HostPort>:1111</HostPort>
  </AdminServer>
  <ResourceLimits>
      <CPUMonitor>1</CPUMonitor>
      <ThreadPoolGC>20</ThreadPoolGC>
      <ApplicationGC>5</ApplicationGC>
      <FLVCacheSize>40</FLVCacheSize>
  </ResourceLimits>
  </Server>

  <ServerDomain></ServerDomain>
</Root>

Note

The node tree, <ResourceLimits>, was omitted from the Flash Communication Server manual. These nodes declare the resource limitations available to the server:

  • <CPUMonitor> A value, in seconds, declaring the frequency Flash Communication Server monitors the CPU.

  • <ThreadPoolGC> A value, in minutes, Flash Communication Server clears unused I/O threads.

  • <ApplicationGC> A value, in minutes, Flash Communication Server clears unused application instances.

  • <FLVCacheSize> A value, in percentage of the total physical memory on the system, that can be used to cache Flash video (FLV) files.

Security

Flash Communication Server provides system administrators with an excellent architecture for security. The default installation is not intended as a locked-down install, and you should become familiar with some of the options you have to tighten security.

Flash Communication Server security is achieved through the server configurations files (XML) and the application you develop. In particular, the <ALLOW> and <DENY> tags in the configuration files let you declare either IP addresses or domains that access the server. By default, the server communicates using port 1935, which was assigned to the Flash Communication Server by the Internet Assigned Number Authority (http://www.iana.org).

The administration API is accessed through port 1111. It is up to you to protect this port through firewall or VPN technology. You can change this port in the Server.xml file within the <HostPort> domain.

The <USER> tags give you control over root-level users who have full operational control over the server. These users are the only users who can connect to the Administration Console.

You can use the <ServerDomain> tag to inform other component servers (such as a Flash Remoting MX-enabled server) of the domain from which the server is communicating.


The Adaptor

You can think of a server adaptor as similar to a domain in a traditional network. It is an isolation of users and hosts and has its own security context. In essence, consider the adaptor as a branch of the server tree. Communication Server applications exist within adaptor virtual hosts, as described in the previous section.

Each adaptor on a server must operate on a different IP address, domain, or port number. For example, the default adaptor communicates on port 1935. A second adaptor that is bound to the same IP address must be assigned to communicate on an alternate port number. Appropriate action on any network firewalls must also be taken so that other ports and IP address can be seen by the intended audience.

Folders

Adaptors are defined with two steps. First, a folder must be created in the server's conf folder (located in the folder where the server was installed). Second, the adaptor must be defined in the Server.xml file. Each adaptor folder must contain a series of elements, including an Adaptor.xml configuration file and a default virtual host folder with its configuration files (Application.xml and Vhost.xml). You will see more on the virtual hosts soon. For now, take a look a the configuration file for adaptors.

Configuration: Adaptor.xml

The Adaptor.xml file is the only file required in the Adaptor folder. This file contains the adaptor settings and is read by the server on reboot. It is an important file to manage the communication port, server resources, and security parameters for a collection of virtual hosts. It has no user context, as the users are defined in the virtual host or the server. It operates as a child under the limitations declared in the Server.xml file. Listing 14.1 shows the default Adaptor.xml document:

Listing 14.1 The default Adaptor.xml document
<Adaptor>
      <ResourceLimits>
            <MaxThreads>100</MaxThreads>
      </ResourceLimits>
      <HostPortList>
            <HostPort>:1935</HostPort>
      </HostPortList>
      <Allow></Allow>
      <Deny></Deny>
      <Order>Deny,Allow</Order>
</Adaptor>

Security

Adaptor security provides domain access context for virtual hosts. It operates under the security context provided by the Server.xml file with the ability to restrict and allow administrator access by domain. The <MaxThreads> node can provide a significant resistance to denial of service attacks by lowering the number of threads, which reduces the amount of CPU processing used by all hosts in the adaptor. It is also a good idea to reduce this number during development, so renegade applications don't bring your server to its knees. Remember, if you have multiple adaptors on a single server, change the <HostPort> node.


The Virtual Host

If isolating applications is important to you, then virtual hosts should handle most operations. If you have multiple developers working on a single Flash Communication Server, then creating virtual hosts is what you need. Virtual hosts are collections of applications and exist under the limitations defined by the adaptor. Virtual hosts are important to ensure the security of independent applications. They are also important to limit applications from consuming 100% of bandwidth and user resources on a particular license of the server. The virtual host configuration file contains many security provisions that ensure applications and users don't overload the server and deny service for other applications.

Consider virtual hosts as "virtual directories" in the context of a web server. The virtual host can also have multiple alias names on the adaptor.

Users

Virtual host users are defined by the administrator in the Server.xml file. You can add, remove, or edit user passwords using the Administration Console. Virtual host administrators can use the Administration Console to add, remove, or edit user passwords only within the virtual host to which they have been assigned. User accounts cannot belong to more than one virtual host. The primary reason for virtual host users is to access the App Inspector during deployment or development procedures.

Folders

Virtual hosts require two sets of folders. First, the configuration folder exists within the adaptor folder in the server's conf folder. The configuration folder contains the Vhost.xml configuration file.

The application folder does not exist within the conf folder for security reasons. The application folder contains the collection of ASC, FLV, and FSO files used by the application. It is a good idea to keep them separate. This folder can exist anywhere on the file system. The developer install of Flash Communication Server places the default applications folder within the flashCom/applications folder, which is where you have been building the exercises in this book. If the server had a web server installed prior to installing Flash Communication Server, the applications folder is placed within the web server's root inetpub/wwwroot/ folder. The application folder can be changed by editing the <AppsDir> node in the Vhost.xml configuration file. You will be required to restart the virtual host when this file is changed.

Each virtual host must have an admin folder in the root of the application folder. This folder is required for the App Inspector and the Administration Console to access the virtual host.

Configuration: Vhost.xml

The Vhost.xml file exists in the root of the virtual host's conf folder. The file provides ultimate control over all applications that are served from it. The <ResourceLimits> node defines limitations of connections, instances, streams, and SharedObjects. It also defines the location of the applications folder in the <AppsDir> tag.

The <Streams> node allows you to define a common location for all stream (FLV) files on the server. You can alias this simply by separating the alias name with the real file path. For example:

<Streams>myCommonStreamDir;c:\myStreams</Streams>

This reference will be available for each application running within the virtual host. Listing 14.2 shows the default Vhost.xml file, including some omissions from the Flash Communication Server manual.

Listing 14.2 The default Vhost.xml file
<VirtualHost>
      <AliasList>
            <Alias>stream</Alias>
      </AliasList>
      <AppsDir>C:\inetpub\wwwroot\flashcom\applications\</AppsDir>
      <RecordAccessLog>true</RecordAccessLog>
      <ResourceLimits>
            <ApplicationInstanceGC>20</ApplicationInstanceGC>
            <MaxConnections>50</MaxConnections>
            <MaxAppInstances>-1</MaxAppInstances>
            <MaxStreams>-1</MaxStreams>
            <MaxSharedObjects>-1</MaxSharedObjects>
      </ResourceLimits>
      <VirtualDirectory>
            <Streams>streamTemp</Streams>
      </VirtualDirectory>
      <DNSSuffix>macromedia.com</DNSSuffix>
      <Allow>all</Allow>
</VirtualHost>

Note

The <ApplicationInstanceGC> node was omitted from the Flash Communication Server Manual. The value within this node specifies, in minutes, how long an inactive application instance's resources will persist.

Security

Access security in the virtual host is controlled by the adaptor. The <ResourceLimits> node, however, allows the server administrator to set limits on bandwidth and users, among others. This is a very important control, because it directly relates to your license. If this isn't set properly, an application could potentially consume the entire server license of users and bandwidth. The <Allow> node allows you limit access to the applications from certain trusted domains.


The Application

A Flash Communication Server application is defined in the virtual host's application folder. The application is a collection of server-side ActionScripts (ASC), Flash video (FLV), and Stored object (FSO) files. All applications are subject to the limitations declared in the adaptor and virtual host configuration files. The application folder is commonly used in development to also store Flash (FLA, SWF) and HTML files. When moved to production, these files should be separated into a folder that is not accessible by the web server. If you access ASC files through a web server, the scripts will be exposed in a web browser—a major security risk. Moving the applications folder to a more secure location simply involves changing the <AppsDir> reference in the Vhost.xml file.

Folders

There are no folders related to the application in the conf folder. Applications are stored within the <AppsDir> folder. Each application folder usually contains a main.asc file that is used to control all server-side ActionScript. Within a single application folder, additional folders can be created by the server. Streams will be created to application instance folders containing FLV (video) files. SharedObjects will also contain application instance folders to save the data in persistent SharedObjects as FSO files.

Configuration: Application.xml

The application configuration file (see Listing 14.3) is located in the virtual host conf folder next to the Vhost.xml file. This is a global file that can be overwritten by each application. Each application within the virtual host can contain its own Application.xml file to override the global one. The file contains settings to micro-manage bandwidth, storage, and general application settings, such as the ability to be loaded when the server starts or reboots.

There are nodes you should be aware of in this file. The <ScriptLibPath> refers to the location of Class files that extend the server-side ActionScript library. This path is referred to when a SSAS load command cannot find a file in the application path. This folder contains the components.asc file and the NetServices.asc file used with the Flash UI components and Flash Remoting MX. It should be protected from access through the web server.

If you are using Flash Communication Server for video streaming, you might consider enabling the <EnhancedSeek> node. This node allows your video to seek accurately to the frame. It consumes additional server resources; however, it does produce a cleaner result for seeking.

Listing 14.3 The Application.xml configuration file
<Application>
      <LoadOnStartup>false</LoadOnStartup>
      <MaxAppIdleTime>1200</MaxAppIdleTime>
      <RecordAppLog>true</RecordAppLog>
      <JSEngine>
      <MaxTimeOut>0</MaxTimeOut>
      <ScriptLibPath> C:\inetpub\wwwroot\flashcom\scriptlib\</ScriptLibPath>
      </JSEngine>
      <StreamManager>
            <StorageDir></StorageDir>
            <GCInterval>20</GCInterval>
            <EnhancedSeek>false</EnhancedSeek>
      </StreamManager>
      <SharedObjManager>
            <StorageDir></StorageDir>
      </SharedObjManager>
      <Client>
            <Bandwidth override="yes">
                  <ServerToClient>250000</ServerToClient>
                  <ClientToServer>250000</ClientToServer>
            </Bandwidth>
            <BandwidthCap override="no">
                  <ServerToClient>10000000</ServerToClient>
                  <ClientToServer>10000000</ClientToServer>
            </BandwidthCap>
      </Client>
</Application>

Note

The <RunTimeSize> node within the <JSEngine> node that is mentioned in the Flash Communication Server manual is no longer used. Also, the default value of 250000 displayed in the <ServerToClient> node is the correct default value. The Flash Communication Server manual made reference to 25000.

Security

Application security is the responsibility of the developer. It is the responsibility of the application to control access to content and streams once a user has entered the system. Application security with the configuration files is limited to capping the bandwidth and the location of the storage.

Macromedia maintains a support site specifically for Flash Communication Server administration. If you are in charge of managing a Communication Server, check out Macromedia's support center for tech notes and updates at http://www.macromedia.com/support/flashcom/administration.html.

With your new knowledge of the server architecture, let's walk through a step-by-step process of creating a new adaptor and virtual hosts for your Flash Communication Server.


Creating Multiple Adaptors and Virtual Hosts

Creating multiple adaptors and virtual hosts is quite simple, but it does involve some manual handling of files and folders. It also requires server restarts, so do not perform these steps on any "live" production servers. In Exercise 14.1, you will create a new adaptor within your Flash Communication Server. This new adaptor will have two virtual hosts, each with their own set of users, which you will work with in Exercise 14.2. This simple scenario can be used if you are planning an application that has multiple developers on it or applications that must be kept totally separate.

You will primarily be working in the file system of your server and within Dreamweaver MX; however, a simple text editor such as Windows Notepad will do. We will use a Developer install of the Flash Communication Server.

There will be references to two sets of folders and files throughout this exercise. To help you out, here is where to find the folders used:

  • Flash Communication Server Install Folder: C:\Program Files\Macromedia\Flash Communication Server MX\

  • FCS Default Application Folder: C:\inetput\wwwroot\FlashCom\

Note

Exercises 14.1 and 14.2 require the Professional version of Macromedia Flash Communication Server MX. The trial version of the Flash Communication Server is the Professional version. To determine if you have the correct version, log into the Administration Console, and click the License tab.

If you own the Personal version of the Flash Communication Server, or are using a shared hosting facility, then you will not be able to run these exercises. You should read through them to understand how the server operates and to acquire a better understanding of using some of the XML configuration files.

Exercise 14.1: Creating a New Adaptor

You have decided to create a new adaptor because you need to bind it to a new specific IP address and port number and may want to only allow certain IP address to access it.

  1. Browse to your Install folder.

  2. Open the configuration folder, conf. This folder contains all adaptors and configuration files for the server and the adaptors.

  3. Select the folder, _defaultRoot_; this is the default adaptor that was installed on your system. The _defaultRoot_ folder is a good "template" for additional adaptors. So let's copy it.

  4. Select the _defaultRoot_ folder and choose Edit, Copy from the Windows Explorer menu.

  5. Paste a new copy of the _defaultRoot_ folder in the conf folder.

  6. Rename the new folder to myAdaptor. This will be the name of your adaptor.

    Doing this simple copy and paste is usually your best method for creating a new adaptor. If your plan includes creating multiple adaptors, then you might consider creating a template adaptor—one that you can set up to easily duplicate. If you are creating the adaptor manually, you must ensure that each new adaptor has the adaptor.xml file. There must also be at least one default virtual host, called _defaultVHost_, which contains the Vhost.xml and the Application.xml configuration files. Explore the new adaptor and you will see these files and folders exist.

    Next, you must register this new adaptor with the server. You do this by editing the Server.xml file. You should be familiar with XML structures before editing this file, as it may have detrimental effects on your server.

  7. Open the Server.xml configuration file located in the conf folder.

  8. Locate the closing </Adaptor> tag (line 65). The next few lines of XML will be inserted between this tag and the </Admin> tag immediately below.

  9. Declare the new adaptor by assigning it the name of the folder you just created.

    <Adaptor name="myAdaptor">

  10. Add the default virtual host reference:

    <VirtualHost name="_defaultVHost_">
    <UserList>
        <User name="">
            <Password encrypt="false"></Password>
            <Allow></Allow>
            <Deny></Deny>
            <Order>Deny,Allow</Order>
        </User>
    </UserList>
</VirtualHost>

    You will get into the details of this shortly, when you create some new virtual adaptors.

  11. Close the <Adaptor> tag:

    </Adaptor>

  12. Save the Server.xml file. Leave it open, if you like; we will be returning to it shortly.

    That's it for registering the adaptor with the server. You will be editing this again when virtual hosts are added. Now you can assign the adaptor a unique IP address and port number in its configuration file, Adaptor.xml.

    Before opening the configuration file, the IP addresses you are using must be registered to your server before restarting the Flash

    Communication Server. Be sure to use IP addresses assigned to you by your system administrator. Assigning an IP address that is assigned to another computer will have adverse affects for both your computer and the other computer using that address.

    Tip

    To add IP addresses in Windows, open the TCP/IP setting for your network adaptor on the server. This can be found in the Network and Dial-up Connections item in the Windows control panel. Usually, if you have a single network card in your server, it will be called Local Area Connection. Open its properties; double-click the TCP/IP protocol to edit the properties. Click the Advanced button. Click the Add button, and enter a new IP address and subnet mask (see Figure 14.3).

    Figure 14.3. Windows 2000 TCP/IP Settings allow you to assign multiple IP addresses to a single network card.

    You will not be able to do this if your server is set up to receive its IP address dynamically from a DHCP sever. You will need to assign a static IP address (provided by your network administrator) before you can continue.

  13. Open the file Adaptor.xml in the myAdaptor folder.

  14. Find the line that contains <HostPort>:1935</HostPort>. This line defines what IP address and what port this adaptor will be referenced by. You cannot have two adaptors communicating on the same port and the same IP address. You can enter any number of IP addresses between the <HostPort> tags, separated by a comma. If you omit the port number, Flash Communication Server will automatically use port 1935. You can even assign this adaptor to multiple ports by entering a value of :1935,80,8080.

  15. Enter the new IP addresses and ports to bind this adaptor to in-between the <HostPort> tags.

  16. Save the Adaptor.xml file, and close it.

Note

You should also assign a static IP address for the _defaultRoot_ adaptor, to ensure that it communicates on a specific IP address. You can do this by editing its Adaptor.xml file located in the _defaultRoot_ folder.

The adaptor will not be registered until you restart the Flash Communication Server. You can restart the server a number of ways, but the easiest is by using the Windows Start menu item: Click Start, Programs, Flash Communication Server MX, Stop Service, and, after it has finished, select Start Service in the same program menu.

Exercise 14.2: Creating a New Virtual Host and Users

With the new adaptor in place, let's create a virtual host and some unique users so they can access the App Inspector. This is done within the adaptor in the conf folder.

  1. Browse to the folder myAdaptor in the conf folder.

  2. Copy the folder _defaultVHost_, and paste the copy in the myAdaptor folder.

  3. Rename the copy to MyNewHost

    You've just created the new virtual host; compare your folder structure to Figure 14.4. The server uses this folder to configure itself only. It will not be used to store applications. Applications can be placed anywhere on the server you like. In the next steps you will register the new virtual host with the adaptor and declare where it will find the applications.

    Figure 14.4. The complete conf directory tree containing a new adaptor with two virtual hosts.

  4. Open the Server.xml file in the conf folder, and locate the </Adaptor> tag that closes the myAdaptor reference. It should be just above the </Admin> tag. You will place the next series of XML tags just above the </Adaptor> tag.

  5. Adding a new XML VirtualHost structure will declare the new virtual host on the adaptor. Simply copy the default <VirtualHost> structure and paste it below the default reference.

  6. Declare the new virtual host, and remember, it's case sensitive:

    <VirtualHost name="myNewHost">

  7. Define an empty UserList structure. You can manually declare users by duplicating this structure, one per user, or use the Administration Console to manage it for you. We will use the Administration Console. Users defined in this list will have limited access to the Administration Console. Use the code:

    <UserList>
    <User name="">
        <Password encrypt="false"></Password>
        <Allow></Allow>
        <Deny></Deny>
        <Order>Deny,Allow</Order>
    </User>
</UserList>

  8. Close the VirtualHost structure:

    </VirtualHost>

  9. Save the Server.xml file.

    The new virtual host will not be defined until you restart the Flash Communication Server. But don't get too far ahead yet; you haven't declared where the applications for this host will be stored. If you are an ISP, a virtual host for each user would be created for each user of the system. Their applications folder could be assigned to their account folder on the server. The applications folder is where users save their ASC files, and where video (FLV) and SharedObject (FSO) files are stored. A drive with enough disk space for these applications should be chosen.

    The example host will be used as a production server, so the applications folders are not accessible through the web server. For security reasons, we will place the applications in a new folder on a large disk array mapped as drive D.

  10. Create a folder called myNewHost_apps on the root of your D drive (or anywhere in your file system).

  11. Create a folder for the Administration Console application. Place a new folder called admin within the myNewHost_apps folder.

  12. Now, register the application folder with your new virtual host, back in the conf folder.

  13. Open the file Vhost.xml in the myNewHost folder.

  14. Locate the <AppsDir> tag. This tag defines where the applications are located for this virtual host. Enter the absolute path to the applications folder. For this exercise, use the following path:

    <AppsDir>d:\myNewHost_apps</AppsDir>

  15. Save and close the Vhost.xml file.

  16. Restart Flash Communication Server MX.

When the server restarts, log into the Administration Console using your normal system login and password. Click on the Administration Users tab, and you should see a visual representation of the new adaptor and the new virtual hosts (Figure 14.5).

Figure 14.5. The Administration Users tab within the Administration Console allows you to manage virtual host users within a simple GUI.

Within the Administration Users panel you can add users to your server or to virtual hosts. Virtual host users will have access to applications within their virtual host only. They will not be able to reboot the server, but they will have access to restart their virtual host. This is a great technique to offer Flash Communication Server as a service with multiple users.

Giving Your Users Access

With your adaptors and virtual hosts set up, you can now give your users their logins and passwords for the App Inspector. If you decide to use only the default adaptor, your users can log into the App Inspector by simply entering their username and password. If you choose to use a different adaptor, then they will have to add the name of the adaptor to which their login is assigned in the username field. Figure 14.6 illustrates a login to a virtual host attached to the adaptor myAdaptor.

Figure 14.6. To log into the App Inspector using the nondefault adaptor, place the adaptor name in front of the username.
    [ Team LiB ]


Summary

As you can see, there is a lot that has been considered with the Flash Communication Server in terms of scalability and security. If you are an ISP, you can clearly see that Flash Communication Server is an enterprise-level server that gives you the option of separating users and reselling your license as a service. Becoming familiar with the configuration files and the server model will help you deliver secure applications that will not overload your server hardware. After all, there is a lot that you can do with the server, and the last thing you want is applications to suffer because the server wasn't tuned in.


Chapter 15. Communication Application Architecture Strategies

You made it to the end of the primary chapters of the book. This chapter will discuss some of the outstanding elements for developing Flash Communication Applications. It will focus on handling connection failures, security, and coding. Because so many elements are involved, this chapter begins with a quick outline of what does what and when.


What Does What When?

Macromedia Flash Communication Server accepts connections and controls streams, SharedObjects, and, in most cases, security. The server should handle business logic and communication with application servers. Using Action Message Format (AMF), it transports data over three protocols: HTTP, HTTPS, and RTMP. By default Communication Server uses ports 1111 for the Administration and App Inspector consoles and port 1935 for Flash player communication.

The Flash player client handles the user interface and prepares data for transport to the server. Like Communication Server, it transports data over the HTTP, HTTPS, and RTMP protocols using AMF. By default is uses port 1935 for Flash Communication Server communication and port 80 for Flash Remoting MX.

The application server handles database operations and exchanges with legacy systems, including such services as email, security, and LDAP servers. It communicates with Flash Communication Server and Flash by sending ActionScript variables inside AMF messages using traditional HTTP or HTTPS web protocols.

The database server handles data storage (warehousing), data relationships, and data security. It communicates with the applications server using protocols determined by the vendor.

The database file includes Microsoft Access, dBase, MySQL, and so on. These limited functionality database technologies provide good development environments, but should be used with caution in production or high-capacity applications.

The web server handles the delivery requests for SWF, HTML, and other web-based assets, such as JPEG, GIF, and PDF. It communicates using HTTP or HTTPS protocols.

The Applications folder (/inetpub/wwwroot/flashCom/applications/) contains Communication Server application folders and provides a space for applications to store streams and SharedObjects. This folder is defined in the virtualHost.xml configuration file.

The Streams folder (/inetpub/wwwroot/flashCom/applications/appDir/streams/) stores and saves recorded Flash video (FLV) files within folders automatically or manually created for each instance of the application.

The SharedObject folder (/inetpub/wwwroot/flashCom/appDir/sharedobject/) stores and saves persistent SharedObject (FSO) files within folders automatically or manually created for each instance of the application.

The ScriptLib folder (/inetpub/wwwroot/flashCom/scriptLib/) contains Flash Communication Server Object extension libraries. Out of the box, this folder will contain two library sets: the UI components library and the Flash Remoting MX (NetServices) library. The folder is defined in the application.xml configuration file.

The Conf folder (/program files/macromedia/flash communication server mx/conf/) contains the server configuration files and the adaptor and virtual host configuration structures.

Local SharedObjects should be used to store data for disconnected clients. Using it in tandem with the remote SharedObject, you can create such applications as a synchronized address book. It can be used to store any ActionScript variable type (objects, arrays, functions or simple variables). The local SharedObject is subject to limits set by the user in the player's Settings panel.

Remote SharedObjects should be used to store common data that is required by connected clients. It can be used to store any ActionScript variable type (objects, arrays, functions, or simple variables). Unlike the local SharedObject, there is no limit for the size of a remote SharedObject.

Get the coffee: Make it strong, creamy, and with enough sugar to make it interesting—not too sweet and not flavored, at the perfect temperature, just right. Don't drink too much or you won't get to sleep tonight.

Flash MX Debugger is used to watch the state of a Flash player and interact with ActionScript functions. You can use this tool to review the structure of a SharedObject, a NetConnection, a RecordSet, or an array.

NetConnection Debugger monitors AMF messages being exchanged over RTMP or HTTP between the Flash player and the Communication Server or the Flash player and an application server. This debugger requires that NetDebug.as be included in your ActionScript. It will also monitor SSAS trace activity on the application instance it is connected to.

The Application Inspector Console loads or unloads application instances on the Communication Server. It also monitors connections, streams, and SharedObject communication, and it provides an output window for SSAS trace activity. It operates by default on port 1111.

The Administration Console manages and monitors users and applications, and it restarts virtual hosts or the entire server. It operates by default on port 1111.


Handling Connection Failures

Connection failures come part and parcel with any technology that uses a remote connection. A Communication Server application is subject to temporary or sustained network interruptions. To build a stable Flash Communication application, you must be prepared to handle these outages and what happens when a client reconnects.

There are two considerations when handling connection failures. Routines must be developed for the server and the client to handle a connection failure independently. If the plug is pulled on a network connection, all messages and persistent data (streams) between the server and client are halted immediately. The NetConnection object on the client and the Application object on the server are your two tools for informing you that a connection has failed.

Both objects use built-in listeners to monitor the state of a connection. The NetConnection object returns an information object with the code NetConnection.connect.closed to the onStatus event if the connection has been lost. The application object will call the Application.onDisconnect event.

These two operations let you manage connection failures. On the client, monitor the code object in the NetConnection onStatus event. When the code is received, execute a script that will determine if the disconnect is expected or unexpected. Unless you have a specific call to the NetConnection.close() method, this status will always be unexpected. Here is a sample script:

nc.onStatus = function(infoObj) {
      if(infoObj.code == "NetConnection.connect.closed") {
            trace("the server connection has terminated");
            runCloseScript();
      }
};

When a client disconnects, the server handles it with the Application.onDisconnect event. The following script calls a custom function, runDisconnectScript(), when a Flash player disconnects:

application.onDisconnect = function() {
      trace("the Client has disconnected");
      runDisconnectScript();
};

Connection failures must be a part of your application plan. They are a natural part of not only the Internet but a "feature" of hand-held devices. Building a strategy for connections and disconnections is imperative. When building your own strategy, consider some of these questions as they relate to both the Flash player application and the server:

  • What happens on the client when the client disconnects?

  • What happens on the server when the client disconnects?

  • What is the synchronization process when a client reconnects?

  • Will local SharedObjects proxy the remote SharedObject in case of connection failure?

  • How will other Flash clients and the server respond when a client connects, disconnects, or reconnects?

These are just some questions you should ask about your application. Clearly there are many more, and you should consider compiling a list of these questions as a form of quality assurance. When designing future applications, test the architecture to ensure they satisfy each question appropriately.

This is just one step in ensuring the integrity of your application. Now, let's look at how you can apply security to your Communication application.


Security

There are two areas of security in Communication applications that you need to consider:

  • The security of runtime environment (Flash Player 6 and the Flash Communication Server, specifically)

  • The security of the application

You will be happy to know that Macromedia provides an environment that is as secure as it can be. The term "secure," however, needs to be put in context.

You can find independent security assessments from @Stake and reviews on both Flash Player 6 and the Flash Communication Server on the Macromedia web site (http://www.macromedia.com/software/flash/whitepapers/).

Users should be confident that the applications running within the Flash Communication Server and Flash player environment will not compromise the integrity of the local client or their server operating systems. Neither technology has an ActionScript interface to directly interact with the server or client operating system. Sandbox security using domain-oriented controls are in place within the Flash player and the Communication Server to prevent cross-site scripting that could jeopardize the integrity of the content within these environments. The environments are secure, but it is your responsibility to ensure the integrity of access and transmission. Let's take a look at these security points separately.

Transmission Security

Transmission security handles the accessibility of data while it is being transported from server to client or from client to server. If you plan to use the Flash Communication Server to share data that is confidential or secure, you should know that the RTMP protocol cannot be encrypted in its 1.0 release. Wrong-doers who can "sniff" the port can gain access to the data during transmission, as they can to nonencrypted email or web pages.

This security hole does not limit your ability to use the Flash Communication Server. You can communicate with full encryption between the client and a Flash Remoting MX-enabled server, such as Macromedia ColdFusion MX or ASP.NET. If you have control over a secure network, such as a VPN, you can deploy Communication application over the trusted domain.

Access Security

Consider a simple username and password authentication script. A user enters a login and password in the Flash interface. If the player sends that login and password directly to the Flash Communication Server over RTMP, it will be sent in AMF format over an unencrypted connection that could be compromised.

If the Flash player sends the login and password through an encrypted HTTPS connection directly to a Flash Remoting MX-enabled application server, a ticketing-type system could be built, where the server would issue a key to the Flash player if the credentials supplied are accepted. This key could then be passed openly to the Communication Server. The Communication Server will confirm the key with the application server and accept or deny the connection based on the response from the application server. No username or password is transmitted insecurely during this process.

Clearly security could be a book unto itself. Developing a security practice is unique to everyone's environment and experience. Your organization might be governed to implement standard security practices and procedures into everything it builds. You might also have a custom practice of implementing security. It is important to be aware of security responsibilities and where you can restrict users entering or listening in to your application.

Macromedia Flash SWF Movie Security

Published SWF movies are not protected and can be opened by non-Macromedia software. Their ActionScript should not be considered secure, because it can be exposed to potential wrong-doers. You should avoid placing sensitive authentication processes within the Flash client. Always use Flash Remoting MX or the Communication Server to handle authentication to the Flash interface, and never store sensitive data within the Flash movie.

The official word from Macromedia SWF security is:

"There are third-party tools available that allow users to edit a rendered SWF to a certain degree, as well as remove the protection tags if an author has accidentally lost their work and needs to reimport the SWF. These tools are not made by Macromedia and carry no guarantees. In addition, they are only mentioned in the context of helping authors regain their own work; the potential for abuse still remains." —Technote: 4109, macromedia.com

To address this issue, third-party (non-Macromedia) ActionScript obfuscators on the market add additional protection to your scripts. A great one can be found at http://www.genable.com/aso/. This software will not encrypt the ActionScript, but it will make it unreadable by human eyes, if it is accessed.

Now that you are aware of some of your security responsibilities, let's move on to some ActionScript techniques.


ActionScript Techniques

I don't know how many times I have seen the phrase "ActionScript is based on the ECMAScript-262 Specification" in Flash books. I don't understand why it is overlooked or not explored further. Flash ActionScript is not some home-grown proprietary language that has no standard of coding. It is an extension of the founding principles and ISO-standard processes of ECMAScript, the ECMAScript-262 Specification, Third Edition—December 1999, to be specific. Server-side ActionScript is extended from the efforts of Netscape Communication's server-side JavaScript 1.5 implementation, which in turn is fully compliant with ECMA-262, Third Edition.

How many of you have actually downloaded the papers associated with ECMA? If you are serious about developing Communication applications, then you must get into the minds of the Macromedia engineers that built it. To fully understand the power of the ActionScript language, download and print these documents, and then put them in a binder marked Flash ActionScript Reference:

  • ECMAScript Language Specification: ftp://ftp.ecma.ch/ecma-st/Ecma-262.pdf

  • Server-Side JavaScript Core Guide: http://developer.netscape.com/docs/manuals/js/core/jsguide14/CoreGuideJS14.pdf

  • Server-Side JavaScript Core Guide: http://developer.netscape.com/docs/manuals/js/core/jsguide15/contents.html

If you belong to an organization that follows an ISO ( http://www.iso.ch/ ) standard practice, then Flash and the Flash Communication Server is an option for you. When someone asks, "To what coding standard do you develop?" you can reply with a big smile and confidence, "ECMAScript, Third Edition—December 1999."

Now to understand how you implement the language specifically in Flash MX, let's look at some style and formatting considerations.

ActionScript Style and Formatting

Flash has evolved a great deal since ActionScript was first introduced in version 4.0. Flash 5 adopted the ECMA standard but selectively chose what it would and would not support, such as Scope chain. Flash MX has now fully adopted the entire standard. Flash is a completely different application of the ECMA language than its original "web page" use. The primary difference is that Flash is a state-full environment, whereas the web page is stateless. This means that variables and objects are discarded whenever the user leaves the web page.

The other clear difference is the authoring environment. Flash was a visual tool that was originally designed for the deployment of vector-based animation. The introduction of ActionScript launched it into an entirely new sector. ActionScript has gone through two major redefinitions since its inception, and it retains backwards compatibility in this third generation. Through its growth, ActionScripting practices have also endured many different variations. It is not a strict language, and allows for the developer to shortcut techniques practiced in other languages.

ActionScript can be placed everywhere, including any frame on any layer or on any MovieClip or button. Although you can place ActionScript almost anywhere, that doesn't mean you should. There is no formal style guide (yet) for Flash applications, so the following suggestions should be considered a single point of view.

Placing Code

ActionScript should only be placed on frames within a single layer in the _root Timeline. It was not possible to do this with Flash 5, but now that you can reference any Flash object (including buttons) from the Timeline, you should kick the old habit of putting ActionScript inside MovieClips or on buttons. If you've done this in the past, you know what a nightmare the technique can be when debugging. Avoid the temptation, and take a bit of extra time now to understand how to access objects from the Timeline. It will save you mountains of time later.

Commenting

Commenting is one of the most important styles to follow. Comment everything. If you think you are over commenting, then you aren't commenting enough. Each command you run, each function, object, or array you build, each time you connect with the server or handle messages returned from the server, add a comment. Here is how you comment in ActionScript:

// this is a single-line ActionScript comment

/*
      this is a multiline
      ActionScript comment
*/

In the book's exercises, you probably noticed a significant number of comments. Write your code as if you are writing a book. This will make you a popular member of the development team, allowing anyone, including new employees, to easily interpret what you built. When you open an application after developing it six months ago, you will understand what is going on in the code. The extra time spent describing what you are doing is a healthy long-term investment to your sanity.

Avoiding Spaghetti Code

Spaghetti code may not be a formal term, but it describes code that is strung together with patches and fixes that start to resemble cancerous tumors—and we all know the fatal results of a tumor. Code is not resistant. This form of coding can be avoided with a solid planning stage, and if a new feature is required, don't just code a solution. Planning upgrades and understanding what elements will be affected will help you avoid bugs, and let you keep the meatballs on your plate, not in your code.

Variable Naming

There are two benefits to naming your variables properly. First, you can use code hinting in the ActionScript Editor and within Macromedia Dreamweaver MX to help you develop. Second, it is a form of self-documentation (once again, more commenting). A variable named n tells you nothing, but a variable named username_str tells you what the value of the variable will represent and the variable's datatype. Instead of building an onSync handler like this:

c.onsync = function(i) {
            for (n in i) { trace("sync message: " + i[n].code); }

write the same function using proper variable suffixes and descriptive variable names:

remoteData_so = function(infoObj_array) {
            for (pos in infoObj_array){
                  trace("sync message: " + infoObj_array[pos].code);
            }
}

Imagine a new member of your development team trying to decipher the first version of the function. It would be a headache, to say the least. If you used the second example, however, the developer probably would be thanking you before you even had a chance to explain what the function does. It's all about communication—see the tie-in?

Using Functions

Use functions to encapsulate code and to practice code reuse. The exercises in this book often encapsulate a series of commands within functions. This technique makes explaining what is going on at particular sections of the code easier. Employing this method of encapsulation will increase your reuse of code, plus ensure that only the script you want to run will run. Functions are essential for Flash Communication applications, because many times you have to wait for a response from the client or server before performing operations. For example, you can't connect to a NetStream before the connection has been accepted and confirmed. To achieve this, the Flash player should wait for the server to respond with a NetConnection.connect.success code before connecting to the NetStream. Failure to wait is the cause of many problems when building Flash Communication applications.

Coding Strategies

Any Flash application you build, with or without the Communication Server, should have a coding strategy. It is particularly important when you build communication applications because of the many elements involved. Three basic strategies you must develop are:

  • Data storage

  • Client/server roles

  • Using the Flash Timeline

There are many more strategies you should consider, but these three are a good place to start.

Data Storage

The worst thing you can possibly do is randomly create a variable, function, or object without a strategy. Variables can contain any ActionScript type. Functions are saved into variables. Objects are instantiated into variables. Arrays, strings, XML, everything you do is stored within a variable. Developing a strategy for variable names and how data will be stored within them is extremely important. This is compounded when you introduce the remote SharedObject into the mix. As you have read, remote SharedObjects announce changes to data slots to every SharedObject connection. If every bit of data is stored in an object within a single slot, the Flash client will have to download and parse the entire slot to handle the changes locally. Some good guidelines are:

  • Create a map of what will be stored and where it will be stored.

  • Make strategic decisions for creating new variables and accessing data.

  • Don't underestimate the power of the local SharedObject, especially for handling disconnected clients (such as the PocketPC).

  • When working with Flash Remoting MX, don't return the entire database recordset. Doing so is inefficient, is unnecessary, and will consume resources of the device. Only return to Flash and the Communication Server what it needed.

You also need to build a strategy for using variables in the _global, local, and MovieClip scopes. Flash Player 6 has fixed a serious interpreter variation from the scope chain defined in the ECMA standard; so in Flash MX, using the variable scope is more efficient and useful. Objects within the _global scope are accessible from any Timeline within the application. The _global scope is useful for maintaining persistent data, such as user information or local SharedObject information. You can also access it from dynamically loaded SWF movies. Local objects are only local to the Timeline they are created on. While they can be accessed anywhere, they are deleted if a movie is unloaded. Object structures are good ways to consolidate variables or arrays. For example, an object that describes a user might look like this:

/* Define the userInfo_object with some initial data */
_global.userInfo_obj = ({name: "Kevin Towes", company = "Pangaea NewMedia"});

/* Add / Update a property of the UserInfo_obj object */
_global.userInfo_obj.phone = "416-922-1600";

/* Read the data from any timeline */
trace("Company" + userInfo_obj.company);

This approach would be much more organized and efficient than storing each variable within the _global root. To clear the user or logout, simply clear the entire object.

Client/Server Roles

Understanding the relationship between the client and the server is extremely important. Developing Flash Communication Server applications is not like developing standard Flash applications. A clear understanding of Flash player logic, business logic, data storage and handling, security, and general application control must be assessed before starting the application. The tutorial chapters in the next part of this book will step you through some advanced exercises that will strategically place logic on the server and on different client interfaces.

There can never be a general rule when it comes to determining where processes will occur; the answer depends on the application you build. Games will differ greatly from a slideshow presentation or a chat room. The server may be responsible for handling login and password authentication or returning data from a database. The client can also do the same thing. Understanding the capabilities of each system and the roles each will play is your first step. Visualizing the scope of it on paper is the next step.

When going through the process, calculate roles for the server and, if required, different interfaces. Determine how each device will handle a disconnection or changing data. For example, you use Flash Communication Server to return a recordset and save it in a SharedObject. Flash client A has the ability to change or add data. When the data is changed and returned to the SharedObject, the server responds by returning the updated recordset to the application server for database inclusion. At the same time, Flash client B can only read the data and responds differently. Now, throw in the possibility of a connection failure anywhere along the path from database server to application server to communication server to client A and client B. Do you see where a seemingly simple operation just got very complex? Drawing it out will help, as will planning a strategy on each system for operating on and handling the exchange of information.

Timeline

Your comfort with the Flash Timeline probably depends on your background. Designers and animators tend to enjoy the Timeline and use it to all of its abilities (sometimes too much), but programmers are just the opposite. Programmers tend to build 100% of the Flash application on a single Frame. I even have seen an extreme case where a programmer wanted nothing to do with the Flash stage and used the attachMovie method to place, code, and interact with MovieClips and buttons. Some designers and animators, of course, can be just as determined to avoid opening the ActionScript Editor.

The Timeline can be a difficult concept, but when you have embraced it and come to a compromise of keyframe design and coding, your world inside Flash will become much more productive and enjoyable.

A technique that goes over well with programmers is to consider the keyframes on the Timeline as completely different applications. Another way to think of them is as different interfaces within the same application. Chapters 9 and 10 illustrate good examples of using the Timeline to develop unique interfaces. This Timeline technique lets the developer build initial functionality and handle interface changes more efficiently. You should also consider the use of #include, pulling ActionScript out of Flash all together and using a JavaScript editor or Dreamweaver MX to produce the ActionScript.


Server Management API

The Server Management API is a series of ActionScript objects that let you build or extend the Server Management tools (App Inspector, Administration Console). You can download the entire dictionary at http://www.macromedia.com/support/flashcom/administration/admin_api_manual/.

Included in this API are a series of methods and properties you can use to either extend the existing Administration Console or to build your own. Applications that use the Server Management API communicate by default on port 1111. Although it is not required for the regular operation of the Flash Communication Server, you should be aware of this library.


Additional Resources

For more guidelines and advice on coding techniques for Flash and the Communication Server, look online. The Macromedia Designer and Developer Centre offers some great resources, as do the standards committees:

  • Flash Communication Server MX DevCentre: http://www.macromedia.com/desdev/mx/flashcom/

  • Flash MX DevCentre: http://www.macromedia.com/desdev/mx/flashcom/

  • ColdFusion MX DevCentre: http://www.macromedia.com/desdev/mx/coldfusion/

  • Mobile DevCentre: http://www.macromedia.com/desdev/mx/mobile/

  • European Computer Manufacturers Association (ECMA): http://www.ecma.ch/

  • International Organization for Standards (ISO ISO-16262): http://www.iso.ch/

  • Netscape Communications: http://developer.netscape.com/docs/manuals/


Summary

You now have a full overview of the Flash Communication Server MX 1.0. The three advanced tutorials in the next part of this book employ the full gamut of techniques, objects, and components of the Flash Communication Server. The Quick Reference guides in the appendices are also essential tools in your development process. A full listing of every client and server object and UI component is quickly available to you there. Appendix C contains a complete listing of every Information object and suggestions for what to do when you receive each object. It will save you a mountain of time and will help you build secure, powerful, and exciting Flash Communication applications.

Welcome to the new world. Be sure to visit the book's web site at http://flashCom.PangaeaNewMedia.ca/ and send me your comments. I will be able to update you there with new Flash Communication Server information.


Part III: Tutorials

16 Build a Technical Support Application

17 Making Faces: The Living Emoticon

18 Build Training and Education: The Virtual Classroom


Chapter 16. Build a Technical Support Application

Application type: Collaborative

UI components used: AVPresence, Chat, PeopleList, ConnectionLight, UserColor, Bandwidth, ListBox, PushButton

Flash objects: SharedObject, NetConnection

SSAS objects: Application, Client

Key points: A live support application using video, voice, and chat

In this chapter you will build a live support application. Corporations use applications like this one to help clients or customers with technical questions about products or services.

Throughout this chapter the person seeking support will be referred to as the customer and the person providing support will be referred to as the representative.

It is not unusual for a company to out-source the technical support and call centers that supply assistance to the customer. One model to solve issues of customer support is to develop a system to allow a customer to communicate the problem using simple technology such as the telephone, or through a computer using video, voice, and text.

Customers' two biggest complaints about technical support are its impersonal nature and the lack of detailed information available to solve complex problems. The Macromedia Flash player provides a platform to deliver customer service applications that can provide a great support experience for both the customer and the company. Although the requirements for the live support application sound very complex, you'll find that it's all surprisingly easy with the Macromedia Flash Communication Server. All you need to do is use prebuilt components with some custom ActionScript, and you are well on your way to revolutionizing the technical support arena. The two main parts to live support are the Live Support Lobby and the Live Support Session.

Let's start in the lobby.


Live Support Lobby Application

The support representative uses the Live Support Lobby as a holding area for customers that are waiting in queue for support. The lobby's sole purpose is to keep a list of clients that need support. Representatives connect to the lobby to connect to the customer they wish to help. When connected, they open a unique Live Support Session, which you will build in the next section. All customers and representatives use only one instance of the lobby.

The Server-Side ActionScript

The Live Support Lobby uses only one Flash Communication Server UI component, the ConnectionLight.

On the server, this application is named LiveSupportLobby. To get ready, create a folder in your FlashCom applications directory called LiveSupportLobby. Then create an empty file called main.asc. This, as always, will be the starting point for creating the application. Next, load the components.asc file to load all the base code for using the components:

load( "components.asc" );

You need to consider what the application will require when it starts. The application.onAppStart method is always called before any users are connected. Just as its name implies, application.onAppStart is called when the application instance is started or run for the first time. This is where you place ActionScript that needs to run before accepting connections. There are four tasks this application needs to do:

  • Keep track of customers.

  • Keep track of representatives.

  • Keep a SharedObject with a list of customers.

  • Have some way to validate representatives.

Initializing the Application (onAppStart)

You can Create an ActionScript object that will be used to look up a client:

application.onAppStart = function(){
      /* Holds all connect clients, key: username value: Server-side client Object */
this.supportClients = new Object();

Later, you will add clients to this object in the application.onConnect method. To store representative connections, create a second new ActionScript object:

/* Holds all connect reps, key: username value: Server-side client Object */
this.supportReps = new Object();

Now you have a way to keep track of both customers and representatives, but you will want a way to share the customer list with other applications. You could create a SharedObject that holds the supportClients object, but that object was created for a way to easily look up customers. In the future, your application may require maintaining the order in which customers connect. To build for this feature, the application will use a separate array for the shared user list:

/* The list of users saved in a SharedObject */
this.userList = new Array();

And of course, create the SharedObject:

/* The SharedObject that holds the list of users */
this.users_so = SharedObject.get( "supportUsers" );
this.users_so.setProperty( "userList", this.userList );

This SharedObject is named supportUsers and is stored in the variable users_so. The property, userList, is then set to match the userList array you just created. Notice that you do not check to see if userList already existed. The application will never start with users already in queue anyway, because it was never there to accept them.

The last item on the list is to validate the representative's connection request. To do this, create another ActionScript Object:

/* Object that is used for rep validation */
this.rep_lookup = new Object();

This will be used later to look up a representative by username and match that to their password. Go ahead and add a couple of users below the previous ActionScript:

/* The representatives */
this.rep_lookup["greg"] = "burch";
this.rep_lookup["kevin"] = "towes";
this.rep_lookup["jessica"] = "smith";

Note

In a real-world scenario, you may want a more robust and secure validation system. Using Flash Remoting MX, you could connect to a ColdFusion web service that checks the username and password rather than having a hard-coded object, as was in this example.

My username is greg and my password is burch. That is all you need in your application.onAppStart to get going! Listing 16.1 is the complete ActionScript. Comments used earlier have been removed to save space.

Listing 16.1 Full listing of SSAS onAppStart
application.onAppStart = function(){
      this.supportClients = new Object();
      this.supportReps = new Object();
      this.userList = new Array();
      this.users_so = SharedObject.get( "supportUsers" );
      this.users_so.setProperty( "userList", this.userList );
      this.rep_lookup = new Object();
      this.rep_lookup["greg"] = "burch";
      this.rep_lookup["kevin"] = "towes";
      this.rep_lookup["jessica"] = "smith";
}
Handling Connection Requests (onConnect)

Next, the application needs an application.onConnect method. This method is called whenever a user connects. This is where the server will decide if the user that is trying to connect is a customer, a representative, or an invalid user.

You will be building your own application.onConnect validation scheme. On the server-side, there are two possibilities when a user connects:

  • The user connects and passes in only one parameter: a username.

  • The user connects and passes in two parameters: a username and a password.

The first scenario would mean the user connecting is a customer. The second means a representative is trying to connect. Customers require only a username in our application because there is no reason to validate their identity. The representative, however, needs to be validated because they will be using administrative controls, such as connecting to a user to help them, opening browser windows on the client's machine, and ending Live Support Sessions.

A simple if statement determines which type the user is. First check if they sent a password. If they didn't, that means they are a customer:

application.onConnect = function( newClient, username, pass ) {
      if( pass == null ){
            trace( "Client Connected- "+username );
}else if...

If the password is not null (meaning the user supplied a password), this ActionScript challenge calls a separate method, called isRep(), which you will build later. The purpose of isRep() is to check the username and password of a representative. The code looks like this:

else if( this.isRep( username, pass ) ){
      trace( "Rep Connected- "+username );
}else...

If the user supplied a username and password that did not match, you have found an invalid user:

}else{
      trace( "Invalid User" );
}

Now you will need to assemble each case with the appropriate ActionScript operations. In the first case, the user is a customer. That means you have to put that customer's name in both of the ActionScript objects associated with a customer. You also need to update the users_so SharedObject:

if( pass == null ){
      trace( "Client Connected- "+username );
      /* Store this client in the supportClientsObject */
      this.supportClients[username] = newClient;
      /* Put it in the SharedObjects userList array */
      this.userList.push(username);
      /* Update the SharedObject */
      this.users_so.setProperty( "userList", this.userList );
}else if...

When a representative's connection has been accepted, store a variable in the client object that identifies the user as a representative. Later, when the user disconnects, you will use this variable to determine which list to remove the user from.

Lastly, add the representive's name to the representatives ActionScript object:

}else if( this.isRep( username, pass ) ){
      trace( "Rep Connected- "+username );
      /* Store that the connected user is a rep, for later use. */
      newClient.isRep = true;
      /* Store this rep in the supportReps object */
      this.supportReps[username] = newClient;
}else...

The invalid user is handled in the last case by rejecting the connection to the Flash Communication Server. To reject connections, use the application.rejectConnection method. Rejecting a connection invokes the NetConnection's onStatus function on the Flash player, sending it the Information object, NetConnection.connect.rejected. The script looks like this:

else{
      trace( "Invalid User" );

      /* Incorrect password */
      application.rejectConnection( newClient );
      /* Nothing more todo, return */
      return false;
}

Now that you have identified the user, let's move on. Declare the username within the Flash Communication Server's UI component framework so the username is recognized by any UI components used in the application:

/**
* Inform the UI Component Framework of the username
* this name will be used by all UI components.
*/
gFrameworkFC.getClientGlobals( newClient ).username = username;

Finally, but most importantly, you have to accept the connection. To do this, use the method application.acceptConnection:

/* accept the connection */
      this.acceptConnection( newClient );
}

Listing 16.2 shows you the complete code, with comments removed to save space.

Listing 16.2 Full listing of SSAS onConnect
application.onConnect = function( newClient, username, pass ) {
      if( pass == null ){
            trace( "Client Connected- "+username );
            this.supportClients[username] = newClient;
            this.userList.push(username);
            this.users_so.setProperty( "userList", this.userList );

      }else if( this.isRep( username, pass ) ){
            trace( "Rep Connected- "+username );
            newClient.isRep = true;
            this.supportReps[username] = newClient;

      }else{
            application.rejectConnection( newClient );
            return false;

      }
      gFrameworkFC.getClientGlobals( newClient ).username = username;
      this.acceptConnection( newClient );
}
Handling User Disconnections (onDisconnect)

Now that the application can handle connection requests, it must also handle client disconnections. There are two user disconnect cases to handle: a representative and a customer disconnect. So, first check the isRep property set in the Client object. If isRep is true, remove the username from the array holding all of the representatives by retrieving the username from the global storage:

application.onDisconnect = function( oldClient ){
      /* Check to see if the client that disconnected is a rep */
      if( oldClient.isRep ){

            var username = gFrameworkFC.getClientGlobals(oldClient ).username;
            /* remove it from the supportReps object */
            delete application.supportReps[username];

}else...

A separate method will be used to clean up customers because there are a few more data bindings. A new function, removeUser, will be called receiving one parameter, the Client object:

}els1e{
/**
* Call the removeUser method passing it the client object. We create this
* method to clean up several things that were stored about the Customer.
*/

      this.removeUser(oldClient);

  }

}

Next, create two helper methods that you have already referenced, isRep and removeUser.

The isRep function is very simple. It is used to validate representatives. It will validate the parameter's username and password against the rep_lookup object created in the application.onAppStart method. Here's how it works:

application.isRep = function( username, pass ){

      /* If they don't have a password, they can't be a rep */
if( pass==null || pass=="" ) return false;

Now, just return the comparison between the value in the username property of rep_lookup and the given password:

/* Return the comparison of the password */
      return this.rep_lookup[username]==pass;
}

The method removeUser is called from the onDisconnect event and is used to clear a user (customer or representative) from the application. A customer's username is stored within the userList array as well as the supportClients object. To remove it from the object, you can simply reference it by the username. For the list, however, it's a bit trickier. You must first loop through the list until you find a match for the username, and then use the Array.splice() method with the array to delete the item:

application.removeUser=function( oldClient ){
      var username = gFrameworkFC.getClientGlobals( oldClient ).username;

      /* Remove the user from the supportClients object */
      delete this.supportClients[username];

      /* Find the user in the userList array and remove it */
      for( var i=0; i<this.userList.length; i++ ){
            if( this.userList[i] == username ){
                  this.userList.splice( i ,1 );
                  this.users_so.setProperty( "userList", this.userList );
                  return true;
            }
      }
}

Listing 16.3 shows a comment-free listing of all the onDisconnect methods and the custom functions that are used to clean up after a user disconnects.

Listing 16.3 Full listing of SSAS onAppStart
application.onDisconnect = function(oldClient){
      if(oldClient.isRep){
            var username = gFrameworkFC.getClientGlobals( oldClient ).username;
            delete this.supportReps[username];

      }else{
            this.removeUser( oldClient );
      }
}

application.isRep = function( username, pass ){

      /* If they don't have a password, they can't be a rep */
      if( pass==null || pass=="" ) return false;

      /* Return the comparison of the password */
      return this.rep_lookup[username]==pass;
}
application.removeUser=function( oldClient ){

      var username = gFrameworkFC.getClientGlobals( oldClient ).username;

      /* Remove the user from the supportClients object */
      delete this.supportClients[username];

      /* Find the user in the userList array and remove it */
      for( var i=0; i<this.userList.length; i++ ){
            if( this.userList[i] == username ){
                  this.userList.splice( i ,1 );
                  this.users_so.setProperty( "userList", this.userList );
                  return true;
            }
      }
}
Create a Unique Application Instance

The custom method connectionToClient is called from the Flash player to open a Live Support Session (application instance). This method is placed in the prototype of the client so it is available to each Flash player connected to the application. The connectToClient method requires two string parameters: rep and client:

Client.prototype.connectToClient = function( rep, client ){...

This method is responsible for creating application instances used to establish a secure communication channel between the representative and the customer. It informs the Flash player of both the customer and representative what application instance to connect to. The variable, instanceId, is incremented each time an instance is created. The variable is incremented to make sure that each Live Support Session is unique.

To initialize an instanceId variable, add the following lines to the end of the application.onAppStart method you scripted earlier:

/**
* This is incremented for each support session and used
* to generate instances of the applications.
*/
this.instanceId = 0;

This function performs three specific tasks:

  • Increments the instanceId

  • Creates a new URI for the users to connect to

  • Calls a method on the Flash player (client-side) that will connect the NetConnection object to the new LiveSupport instance

Listing 16.4 shows the code that accomplishes these tasks.

Note

The LiveSupport application will be created in the next section.

Listing 16.4 Full listing of connectionToClient
Client.prototype.connectToClient = function( rep, client ){

      /**
      * We are going to launch a new instance of the LiveSupport application
      * so we need to increment the instanceId variable
      */
      application.instanceId++;

      /* The URI that we are going to pass to the client */
      var rStr = "rtmp:/LiveSupport/"+application.instanceId;

      /* Tell both the rep and the client to connect to the new URI */
      application.supportReps[rep].call("startSupport", null, rStr);
      application.supportClients[client].call("startSupport", null, rStr);

}

Note

I refer to application.instanceId and not this.instanceId because this ActionScript exists within the Client object, not the Application object where instanceId exists.

The last two lines call the startSupport method for both users. The startSupport methods are defined on the client-side ActionScript and will handle the new URIs they have been assigned. That is it for the server-side code for the lobby. The lobby is the most complicated part of the entire support application because it uses a lot of custom ActionScript. The entire LiveSupport application is made up of the Flash Communication components so there is not much additional ActionScript required.

The Client-Side ActionScript

The client-side (Flash) ActionScript will handle both the Lobby and the Support Tool scenarios in one application. A customer will use a different Flash movie than a representative. You will begin by building the ActionScript needed for the user to connect and wait in the lobby. Then you will construct the user interfaces for the customer user and the representative.

Exercise 16.1: Building the Client User Interface

  1. To start building the client interface, create a new Flash movie called Client_Support_App.fla.

  2. Open that movie in Flash and create three layers. Name the top one Actions, the middle one Connection Light, and the last one Client Screens.

    The client Flash movie is about as simple as it gets. All the client must provide to enter the system is a username. Then, the client sits patiently and waits for a representative to transfer to them. With that in mind, there are only a few things that you need to build:

    • An input text field for clients to enter a username

    • A PushButton component (from the Flash UI components) that the user can press to log in

    • A dynamic text field for displaying status messages, such as "You need to log in" or "Please be patient; a representative will be with you shortly"

    • The ConnectionLight component so the client can see his connection status

    Use Figure 16.1 as a guide to layout your components.

    Figure 16.1. The first screen for the client application.

  3. Select the Client Screens layer. Give the field an instance name of loginField and make sure it's set to an input field.

  4. Drag a PushButton from the Flash UI components onto the Client Screens layer next to the login field.

  5. Select the PushButton on the stage and give it an instance name of login_btn.

  6. Click on label in the Component Parameters of the PushButton and type in Login. You should see this update live on the screen in your button. Next, click on Click Handler and type in onLogin. That's it for the PushButton.

  7. Create another text field on the Client Screens layer and size it all enough to fit about three lines of text. Give it an instance name of statusField. Make sure that it is set to Dynamic Text. In the Properties panel, set it to multiline.

  8. Type the text Welcome to the Live Support Application. Please enter a username below to be placed in line. in the statusField text field.

  9. On the Connection Light layer place the ConnectionLight component and give it an instance name of connectionLight_mc.

    That's it for the user interface! Now you need to write the ActionScript that makes all of these work.

  10. Open the Actions panel (F9) and add the following code:

    /* Setup NetConnection */
nc = new NetConnection();

  11. Instantiate the NetConnection object to the nc variable.

  12. Create the Click Handler onLogin, which is used to connect to the LiveSupportLobby application. The onLogin function will receive the username from the loginField and send it as an argument to LiveSupportLobby. Use the following code:

    onLogin = function(){
      username = loginField.text;
nc.connect("rtmp:/LiveSupportLobby",username);

  13. Connect the ConnectionLight UI component connectionLight_mc:

    connectionLight_mc.connect(nc);

  14. Update the statusField text box to inform that the user has entered the application:

    statusField.text="A Representitive Will be with you shortly. Thank you for your patience.
  "

    When the user's connection is accepted, the login field and Login button will be deactivated because the CUSTOMER is waiting in the queue for a representative.

  15. Set the selectable property of the statusField to false, changing some colors to make the status change apparent to the user:

    loginField.selectable = false;
loginField.background = true;
loginField.backgroundColor = 0xCCCCCC;
loginField.textColor = 0x999999;

  16. Call the pushButton.setEnabled method for the Login button and pass it a value of false. Close off the bracket for the onLogin function:

          login_btn.setEnabled(false);
}

  17. Add a stop() action so the movie does not continue playing.

    /* Make sure to stop the playhead! */
stop();

Listing 16.5 shows the complete code with limited comments. Use the code in Listing 16.5 to confirm your ActionScrtipt.

Listing 16.5 Full Flash ActionScript for Frame 1, ActionScript layer
nc = new NetConnection();
onLogin = function(){
      username = loginField.text;
      nc.connect("rtmp:/LiveSupportLobby",username);
      connectionLight_mc.connect(nc);
      statusField.text="A Representitive Will be with you shortly. Thank you for your
  patience."
      loginField.selectable = false;
      loginField.background = true;
      loginField.backgroundColor = 0xCCCCCC;
      loginField.textColor = 0x999999;

      login_btn.setEnabled(false);

}
stop();

That does it for the lobby part of the application. Figure 16.2 shows the completed application. In the section "Live Support Session," you will be building upon this movie to handle live support sessions, as well. Next, you will create the Flash movie used by the representative user.

Figure 16.2. The user has logged in and is waiting for a representative.

The Representative User Interface

The representative user interface consists of two interface screens: one for the representative to log in and one to select the user to provide support.

Start by first creating a new Flash movie called Representative_Support_ App.fla. Open the movie in Flash MX, and then create three new layers as follows:

  • Actions

  • Connection Light

  • Representative Screens

Now you're ready to start by building the Login interface.

Exercise 16.2: Representative Login Interface

Follow these steps to create the Representative Login interface:

  1. Create two text fields on the Representative Screens layer. One will be used for a username and the other for a password. Give the username field the instance name of loginField and set it to single line input field. Give the password field an instance name of passwordField and set it to password where it says Single Line.

  2. Drag a PushButton component onto the same layer next to the two fields. Give this an instance name of login_btn. For the Label parameter of the component, type in Login, and for the Click Handler, type in onLogin.

  3. Drag a ConnectionLight component onto the Connection Light layer. Give it an instance name of connectionLight_mc.

    That completes the user interface setup of the representative login screen. Use Figure 16.3 as your guide to lay out the screen. Next, you will set up the Click Handler that connects the representative.

    Figure 16.3. The first screen that the representative sees.

    Now that your interface is built, let's continue this exercise by adding the ActionScript required. Place the following ActionScript in Frame 1 on the Actions layer.

  4. Create your NetConnection object nc:

    /* Setup NetConnection */
nc = new NetConnection();

  5. Create the function onLogin to be the Click Handler of the Login button. This method will return the text property from loginField for the username and the text property from passwordField for the password. It will connect the NetConnection object passing the connection string, rtmp:/LiveSupportLobby, and the argument's username and password. The code you need is:

    onLogin = function(){
      username = this.loginField.text;
      password = this.passwordField.text;
nc.connect("rtmp:/LiveSupportLobby",this.username,this.password);

  6. Connect the ConnectionLight component, connectionLight_mc:

    connectionLight_mc.connect(nc);

  7. Remember that SharedObject that holds a list of clients, users_so? You will use that now to keep the representative up-to-date on what clients need help. Get the reference to the SharedObject:

    supportUsers = SharedObject.getRemote("supportUsers",nc.uri);

  8. Define an onSync method for updating the list when it has changed:

    supportUsers.onSync = function(args){
      /* Remove all items from the list box */
user_lsb.removeAll();

    Always remember to place the onSync method before you connect; this technique will ensure that no onSync messages are missed.

  9. Loop through the items in the user_list property and add them to a Flash UI components ListBox. The ListBox will have the instance name user_lsb, and you will be adding it in the next exercise.

    /* add each item to the list box */
      for(var i in this.data["userList"]){
            user_lsb.addItem(this.data["userList"][i]);
      }
}

  10. Connect the SharedObject:

    supportUsers.connect(nc);

  11. Add a gotoAndStop() action to move the play head to the next screen (on Frame 2):

    gotoAndStop(2);

    The screen will have a ListBox that will display a list of the customers and a PushButton to transfer the representative and the customer to a Live Support Session.

Exercise 16.3: Representative Customer Selection Interface

Now you are ready to create the user list screen.

  1. Insert an empty keyframe on Frame 2 of the Representative Screens layer by right-clicking on the second frame of the layer and selecting it from the list.

  2. On the ConnectionLight and Actions layers, right-click on Frame 2 and select Insert Frame.

  3. Select the second frame you just created on the Representative Screens layer and place a ListBox, and give it an instance name of user_lsb (see Figure 16.4). That's all you have to do for the ListBox.

    Figure 16.4. The screen where a representative chooses a client to help.

  4. Drag a PushButton component on to the second frame of the Representative Screens layer. Give it an instance name of c2c_btn. This button will have a long label, so make its width 175 pixels.

  5. Type the phrase Connect to Selected Client in the label parameter of the PushButton. As its Click Handler, enter onConnectClient.

  6. Add the function onConnectClient to call the connectToClient server-side method you created.

  7. Return to Frame 1 of the Actions layer, and add the following ActionScript:

    onConnectClient = function(){
      /* Get the username of the selected user */
      var user = this.user_lsb.getSelectedItem().label;

      /* Make sure a user is in fact selected */
      if(user!=null){
            /**
            * Call the server-side method passing it the
            * Representatives username and the selected
            * Client's username
            */
            this.nc.call("connectToClient",null,this.username,user);
      }
}

    Note

    The first parameter of the NetConnection call method is the method name and the second is the callback. The rest of the parameters can be what you want. Get used to passing in null as the second parameter if you do not plan on using callbacks.

  8. Add a stop() action as the last ActionScript item on the frame:

    /* Make sure to stop! */
stop();

The lobby part of the representative Flash movie is done. In the next section, you will create the Live Support Session that will build on this movie. Listing 16.6 shows a complete and comment-free version of the code for this exercise.

Listing 16.6 Flash ActionScript listing for representative interface
nc = new NetConnection();

onLogin = function(){
      username = this.loginField.text;
      password = this.passwordField.text;
      nc.connect("rtmp:/LiveSupportLobby",this.username,this.password);
      connectionLight_mc.connect(nc);
      supportUsers = SharedObject.getRemote("supportUsers",nc.uri);
      supportUsers.onSync = function(args){
            user_lsb.removeAll();
            for(var i in this.data["userList"]){
                  user_lsb.addItem(this.data["userList"][i]);
            }
      }

      supportUsers.connect(nc);
      gotoAndStop(2);
}
onConnectClient = function(){
      var user = this.user_lsb.getSelectedItem().label;
      if(user!=null){
            this.nc.call("connectToClient",null,this.username,user);

      }
}

stop();


Live Support Session Application

Your next challenge is the interface and ActionScript used to engage a one-on-one session between the customer and the representative. A Live Support Session is actually a new instance of the application LiveSupport. Therefore, throughout this portion of the project, I will refer to application instances of LiveSupport as Live Support Sessions.

The server-side part of the LiveSupport application is actually very simple. It handles users connecting and disconnecting, provides a way to end a call, and enables a representative to open a browser window on the client's machine and send the browser to a specified URL.

Exercise 16.4: The Server-Side ActionScript (SSAS)

The server-side ActionScript will be our first target. This SSAS will determine if the user logging into the system is a representative or a customer. It will also set up special functions that will be called by the Flash player. Listing 16.7 contains the full ActionScript listing for your review.

  1. Create a folder in your applications directory named LiveSupport.

  2. Create a file in that folder named main.asc. Open this file in Macromedia Dreamweaver MX or your preferred code editor.

  3. This application will use the Flash Communication Server UI components, so the Component Framework is required. Load in your components.asc file:

    load( "components.asc" );

  4. You need to handle users requesting a connection to the Application instance. This time when a user connects they will pass a username and a value declaring if they are a Representative. Accept the connection request using application.acceptConnection:

    application.onConnect = function( newClient, username, isRep ){
trace( "Client Connected" );
      /* Accept the connection */
      application.acceptConnection( newClient );

  5. Register the username in the global storage of the Flash Communication Component Framework:

    /**
* Inform the UI Component Framework of the username
* this name will be used by all UI components.
*/
gFrameworkFC.getClientGlobals( newClient ).username = username;

  6. Store the user's SSAS Client object in the variable repUser or clientUser depending on the value of the parameter isRep:

    /* Check to see if they identified themselves as the rep */
      if( isRep ){
            /* Save as the repUser for later use */
            this.repUser = newClient;

      }else{
            /* Save as the clientUser for later use */
            this.clientUser = newClient;
      }
}

  7. In most cases you would define application.onDisconnect next. We're skipping ahead, however, to extend the Client ActionScript object's method for ending a call, because this is all that it will use. The Client object's method will be called endCall and it will take no parameters. It will do three things: notify the users that the call is ending, disconnect the users, and clear all SharedObjects to make sure it cleans up after itself. Extend the Client object prototype with the new endCall method:

    Client.prototype.endCall = function(){
      trace( "Ending Call" );

      /* The call has ended, tell both the clientUser and repUser */
      application.clientUser.call("endCall");
      application.repUser.call("endCall");

      /* Make sure to disconnect the users */
      application.disconnect(this.clientUser);
      application.disconnect(this.repUser);

      /* Clears all the SharedObjects */
      application.clearSharedObjects("/");
}

    This ActionScript notifies both the customer and representative interfaces that the support exchange is over by calling the endCall method on their NetConnection objects. This ActionScript will be created in the next exercise.

  8. Define the application.onDisconnect method:

    application.onDisconnect=function(){
      /* If anyone disconnects, the call must end */
      this.repUser.endCall();
}

    This method is really simple now because you have implemented endCall. The application.onDisconnect method calls the endCall() method on the repUser object.

  9. Extend the Client object prototype with the new sendURL method to enable the representative to push a web site's URL to a customer's computer:

    Client.prototype.sendUrl = function( url ){
      trace( "Sending client to url: " + url );
      application.clientUser.call( "receiveURL", null, url );
}

    This "push" method opens a new web browser window on the customer's computer to a given location. You will build the receiveUrl handler later in Flash MX.

Overall this application was very simple, but it will be full featured thanks to the Flash Communication components. The LiveSupport application will have full video, voice, and text chat capability, plus it can send a client's browser to locations given by the representative.

Next up, you will build upon the Flash interfaces you previously made in Flash MX. You will now add the screens to handle the LiveSupport application.

Listing 16.7 shows the complete server-side ActionScript for the LiveSupport application.

Listing 16.7 SSAS listing for the Live Support Session application
load( "components.asc" );

application.onConnect = function( newClient, username, isRep ){
      trace( "Client Connected" );
      application.acceptConnection( newClient );
      gFrameworkFC.getClientGlobals( newClient ).username = username;
      if( isRep ){
            this.repUser = newClient;
      }else{
            this.clientUser = newClient;
      }
}

Client.prototype.endCall = function(){
      trace( "Ending Call" );

      application.clientUser.call( "endCall" );
      application.repUser.call( "endCall" );

      application.disconnect( this.clientUser );
      application.disconnect( this.repUser );

      application.clearSharedObjects("/");

}

application.onDisconnect=function(){
      this.repUser.endCall();
}

Client.prototype.sendUrl = function( url ){
      application.clientUser.call( "receiveURL", null, url );
}

Exercise 16.5: The Flash Interface

Open the file Client_Support_App.fla, that you created when you built the client interface. In this exercise, you will extend this Flash movie with the support application interfaces for the customer.

  1. Insert empty keyframes on the second frame of the Client screens and Actions layers. On the Connection Light layer, just insert a frame.

  2. Using Figure 16.5 as a layout guide, add the following Communication UI components on Frame 2 of the Client Screens layer :

    • AVPresence Set Instance Name to clientVideo_mc, X to 15, and Y to 10.

    • AVPresence Set Instance Name to repVideo_mc, X to 400, and Y to 10.

      Figure 16.5. The LiveSupport screen of the client application.

    • Chat Set Instance Name to chat_mc, X to 30, and Y to 210.

    • UserList Set Instance Name to userlist_mc, X to 385, and Y to 220.

    • UserColor Set Instance Name to usercolor_mc, X to 10, and Y to 160.

    • Bandwidth Set Instance Name to bandwidth_mc, X to 410, and Y to 160.

    The ConnectionLight component should still be there from the previous screen, because you did not add an empty keyframe.

  3. Select Frame 2 on the Actions layer, and open your ActionScript panel (F9). Connect all the Flash Communication UI components that you placed on the stage to the NetConnection object:

    /* Connect our components to our NetConnection object */
chat_mc.connect(nc);
userlist_mc.connect(nc);
usercolor_mc.connect(nc);
bandwidth_mc.connect(nc);
connectionLight_mc.connect(nc);
clientVideo_mc.connect(nc);
repVideo_mc.connect(nc);

  4. The AVPresence component requires some special attention. Normally, the component requires a user to click to publish their video, but you want the video to start on its own. To accomplish this, you have to call the setUsername method to tell the component the username. You then have to tell the component to start publishing the stream. Because this Flash movie is used by the customer, ActionScript calls these methods. Add the following code to start the AVPresence component publishing:

    /**
* We are a client, so use the clientVideo_mc to represent our video.
* To do this, we pass our username to it, and then call the
* startPublish method to start the stream.
*/
clientVideo_mc.setUsername(username);
clientVideo_mc.startPublish();

  5. We still have to define some methods in the NetConnection object, nc, that are called from the server-side ActionScript:

    • nc.startSupport(uri) Called when the application should connect to a LiveSupport instance.

    • nc.endCall() Called when a support call has been ended.

    • nc.receiveUrl(url) Called when the application should open a browser window with the supplied URL.

    To get ready to define these, move your play head by clicking on Frame 1 on the Actions layer. This next series of code is placed at the bottom of the ActionScript you previously built, but above the stop() action.

  6. Create the startSupport method to call the function setUpSupport passing the URI:

    /**
* The command from the server to go ahead and start a support
* session, while handing it the URI to connect to for its support session.
* We set the statusField's visibility to false since we won't be using it.
*/
nc.startSupport = function(uri){
setUpSupport(uri);
}

  7. Create the setUpSupport method to receive the URI:

    function setUpSupport(uri){

  8. Call the NetConnection.connect method in the nc variable using the URI argument to establish the connection to the new Application instance:

    nc.connect(uri,this.username,false);

  9. Using gotoAndStop(), move the play head to Frame 2, and close the setupSupport() function:

          gotoAndPlay(2);
}

    When a call ends, the Flash movie returns to Frame 1 and closes the connection updating the statusField text prompt you created in the Lobby application.

  10. Change the statusField text to read: "Thank you for your call. Please feel free to return if you have further problems." The code you need is:

    /**
* The command that the call has ended. The application then goes to the login
* screen and update the statusField to show a new message. Note that we set
* its visibility to true.
*/
nc.endCall = function(){
      gotoAndStop(1);
      this.close();
      statusField.text="Thank you for your call. Please feel free to return if you have
  further problems."
}

  11. Create the receiveUrl method handler:

    nc.receiveURL = function(url){
      getURL(url,"_blank");
}

    This is a very simple function because all it has to do is execute the getURL action and give it the URL it was passed.

That completes the entire Client_Support_App.fla. You can see the complete code for Frame 1 in Listing 16.8. Because you did not add code to Frame 2, it will not be repeated here.

Listing 16.8 Full ActionScript of Client_Support_App.fla
nc = new NetConnection();

nc.startSupport = function(uri){
      setUpSupport(uri);
}

nc.endCall = function(){
      gotoAndStop(1);
      this.close();
      statusField.text="Thank you for your call. Please feel free to return if you have
  further problems."
}

nc.receiveURL = function(url){
      getURL(url,"_blank");
}

onLogin = function(){
      username = loginField.text;
      nc.connect("rtmp:/LiveSupportLobby",username);
      connectionLight_mc.connect(nc);
      statusField.text="A Representitive Will be with you shortly. Thank you for your
  patience."
      loginField.selectable = false;
      loginField.background = true;
      loginField.backgroundColor = 0xCCCCCC;
      loginField.textColor = 0x999999;
      login_btn.setEnabled(false);
}

function setUpSupport(uri){
      nc.connect(uri,this.username,false);
      gotoAndPlay(2);
}

stop();

Exercise 16.6: The Representative Application

Your last task is to create the representative application. You will extend the Representative_Support_App.fla to handle Live Support Sessions, so open it now in Flash MX.

  1. Insert empty keyframes on the third frame of the Actions and Representative Screens layers.

  2. Insert a frame on the third frame for the Connection Light layer.

  3. Right-click on the second frame of Client_Support_App.fla's Client Screens layer and select Copy Frame. Then right-click on the Representative Screens layer's third frame in Representative_Support_App.fla and select Paste Frames.

  4. Delete the Bandwidth component because the representative won't need it.

  5. On the third frame of the Actions layer, add the following ActionScript:

    /* Connect our components to our NetConnection object */
chat_mc.connect(nc);
userlist_mc.connect(nc);
usercolor_mc.connect(nc);
connectionLight_mc.connect(nc);
clientVideo_mc.connect(nc);
repVideo_mc.connect(nc);

  6. Because this is the Representative application, you will set up the repVideo_mc this time. Add the ActionScript:

    /**
* We are a rep, so use the repVideo_mc to represent our video.
* To do this, we pass our username to it, and then call the
* startPublish method to start the stream.
*/
repVideo_mc.setUsername(username);
repVideo_mc.startPublish();

    That completes the third frame of ActionScript.

  7. On the third frame of the Representative Screens layer, you have to add a few things (see Figure 16.6). Start with a PushButton to end the call. Add a PushButton component with the following settings:

    Figure 16.6. The LiveSupport interface of the representative application.

    Instance Name: endCall_btn

    X: 445

    Y: 375

    Label: End Call

    Click Handler: onEndCall

  8. Again, on the same frame and layer, add a second PushButton to send the URL to the server-side method sendUrl. Use the following settings:

    Instance Name: sendUrl_btn

    X: 275

    Y: 375

    Label: Send URL

    Click Handler: onSendUrl

  9. On the same frame and layer, add a dynamic text box to the left of the Send URL button. In the Properties panel, give it the instance name of sendUrlField and set the multiline property to false. The representative will use this text box to input the URL.

  10. Now you're ready to add the new ActionScript this application requires. You will add it to Frame 1 on the Actions layer. Create a startSupport method just like the one you added to the client application:

    /**
* The command from the server to go ahead and start a support
* session, while handing it the URI to connect to for its support session
*/
nc.startSupport = function(uri){
         setUpSupport(uri);
}

  11. Define the setUpSupport function:

    /**
* First we connect to the new uri passing our username, and true identifying
* ourselves as a rep. We then goto frame 3 which holds the screen for a
* support session
*/
setUpSupport=function(uri){
      nc.connect(uri,this.username,true);
      gotoAndStop(3);
}

  12. Create the handler endCall:

    nc.endCall = function(){
      this.connect("rtmp:/LiveSupportLobby",username,password);
      /* We must reconnect the connection light when we change connections */
      connectionLight_mc.connect(nc);
      supportUsers.connect(nc);
      gotoAndStop(2);
}

    This function operates differently from the one in the customer application, because the representative will want to return to the lobby to help another client. The connection light and SharedObject are reconnected, and then the play head is returned to Frame 2.

  13. Define the Click Handler to spawn a new browser on the customer's computer:

    /**
* This is the handler used by the "Send URL" button.
* When pressed the sendUrl is called on the NetConnection object.
*/
onSendUrl = function(){
      var url = sendUrlField.text;
      if(url!=""){
            nc.call("sendUrl",null,url);
      }
}

    This function will pass the URI to the sendUrl() handler within the server-side ActionScript (main.asc).

  14. Create the onEndCall Click Handler to close the customer's NetConnection:

    /**
* This is the handler used by the "End Call" button.
* When pressed the endCall method is called on the NetConnection object.
*/
onEndCall = function(){
      nc.call("endCall");
}

    Because you already created the server-side method for ending a call, this handler is very simple. When the endCall method is called on the server, it will do its clean up, invoke the endCall method of the connected clients, and disconnect them.

Listing 16.9 shows the complete code for the first frame of the Actions layer, including the original code appended.

Listing 16.9 Final ActionScript for Representative_Support_App.fla
nc = new NetConnection();

nc.startSupport = function(uri){
      setUpSupport(uri);
}

nc.endCall = function(){
      this.connect("rtmp:/LiveSupportLobby",username,password);
      connectionLight_mc.connect(nc);
      supportUsers.connect(nc);
      gotoAndStop(2);
}

onLogin = function(){
      username = this.loginField.text;
      password = this.passwordField.text;
      nc.connect("rtmp:/LiveSupportLobby",this.username,this.password);
      connectionLight_mc.connect(nc);
      supportUsers = SharedObject.getRemote("supportUsers",nc.uri);
      supportUsers.onSync = function(args){
            user_lsb.removeAll();
            for(var i in this.data["userList"]){
                  user_lsb.addItem(this.data["userList"][i]);
            }
      }
      supportUsers.connect(nc);
      gotoAndStop(2);
}

onConnectClient = function(){
      var user = this.user_lsb.getSelectedItem().label;
      if(user!=null){
            this.nc.call("connectToClient",null,this.username,user);
      }
}

onSendUrl = function(){
      var url = sendUrlField.text;
      if(url!=""){
            nc.call("sendUrl",null,url);
      }
}

onEndCall = function(){
      nc.call("endCall");
}

setUpSupport=function(uri){
      nc.connect(uri,this.username,true);
      gotoAndStop(3);
}
stop();

Now you are ready to test your application. To do so, you should publish both Client_Support_App.fla and Representative_Support_App.fla, and then run the client SWF and log in. Next, open the representative SWF and log in with one of the usernames and passwords you defined on the server-side. You should then see a list box with the other username you used to log in. You can then connect to this user and have fun chatting with yourself! You can send the Client_Support_App.swf to your friends and have them connect while you use Representative_Support_App.swf to pick and choose who to speak with.


Summary

Congratulations! You now have a live support application. Without spending millions on custom software, your company can have live online support—the sort of support that brings and keeps customers.


Chapter 17. Making Faces: The Living Emoticon

Application type: Collaborative

UI components used: AVPresence, Chat, PeopleList, ConnectionLight

Flash objects: SharedObject, NetConnection

SSAS objects: Application

Key points: Dynamically move objects around the screen

When the AOL, YAHOO!, and the MSN messengers started supporting emoticons, they captured something amazing. Emoticons (emotional icons) started as text sequences in e-mail messages that simulated facial expressions::-) for a smile, ;-) for a wink, or :-b for sticking out your tongue. Instant messengers took the idea one step further by replacing the text sequences with simple graphics. Now you can add even more personality to emoticons.

Figure 17.1 is a sneak peak at what you will build in this tutorial. It will use the concept of emoticons to illustrate how you can build collaborative applications. The SharedObject will take center stage in this tutorial, and you will learn some efficient coding techniques that were introduced with Macromedia Flash MX. It's a fun project that you can use as a foundation for constructing some incredible collaborative applications.

Figure 17.1. The finished Living Emoticon application running with four users and a video feed.

Note

This tutorial uses a series of images that can be downloaded at http://flashcom.pangaeanewmedia.ca/.

The Living Emoticon is a great application that will make your child or spouse drop Mr. Potato Head for at least five minutes and be entertained. You will phone your friends and tell them to get online to try this thing. The Internet providers of the world will seize as the world falls in love with the Living Emoticon. This tutorial alone will be worth the price you paid for this book! Ok, maybe that was going a bit too far, but trust me, you will love it.

The Living Emoticon lets you move the position of multiple MovieClips on a shared Flash stage. For this example, I chose to use face parts because Flash Communication Server is really about the human experience. Users connected will all use the same interface (no controller or lobby is used). Users will collaborate making faces while engaged in a live chat.

Technically, it is a very useful application with some great ActionScript. You can use this application as a foundation for building collaborative diagrams, floor plans, or games. The tutorial uses many Flash UI components with a simple implementation of the SharedObject. Yes, simple. This application also employs some unique scripting techniques that allows you to easily connect as many MovieClips as you need.

The key to the whole application is monitoring everyone's mouse position when an object is in Drag (mode)—get your mind out of the gutter, Drag is a perfectly normal function of Flash.


The User Perspective

Users have no access to moving the pieces around until they log in. When someone logs, the chat window and people list engage, and if there is a video feed, it starts. If not, then the user can attach to the feed to transmit.

Once a user logs in, the cursor UI component displays the user's mouse position and everyone will see where everyone else is, and what they are up to.

Users also can change the name of the faces they make. It's a great way to taunt the other users.

All users have equal rights on the system.


Putting Macromedia Flash MX in Developer Mode

Well, Developer mode is not an official mode, but it is a more efficient use of your work space. This application will be built completely within a single frame over a number of layers. Moving the Timeline panel to the left side lets you use your screen real estate for the Flash stage. You can move any of the Flash MX panels by clicking and dragging the dots next to the title of the panel. This arrangement takes a bit to get used to, but as you can see in Figure 17.2, it is a great setup when you are working on a single frame.

Figure 17.2. An optimized Flash MX interface for single frame and multilayer coding.

To see the contents of the frames, set the Timeline to Preview mode by clicking the Timeline Properties at the top right of the panel. Snap the library and the UI components to the right pane. Place the ActionScript in the middle and the Properties panel at the bottom. The Communication App Inspector can rollup on to the title bar.

Working in Flash is best when you have multiple monitors, but if you are forced to work on a laptop or a small screen, managing your interface will save you time and stress. The following sections provide a few more tips.


The Interface

The interface is simple, you can choose to include or exclude the components. Use Figure 17.3 as your guide for the interface.

Figure 17.3. The Timeline displaying Frame 1 with the "Preview in Context" Timeline option.

  1. Create seven Layers in your Timeline as illustrated in Figure 17.3. Name the Layers as follows and in the same order:

    Actions Will contain all ActionScript for the entire movie.

    Cursor Will contain the Cursor UI component.

    FaceParts Will contain a series of MovieClips for each face element.

    FaceBGs Will contain the face backgrounds.

    UI Components Will contain the Communication UI components, AVPresence, Chat, and PeopleList.

    Login Will contain the login text box and the PushButton UI component.

    BGs Will contain any background artwork. In the example it will be the gray boxes below the UI components.

  2. Click Frame 1 of the Login layer.

  3. Add a Text input box to the top of the stage. Give it the instance name login_txt. This will be used for the user to enter his name.

  4. Drag a PushButton UI component next to the text box. Give it the label login and the Click Handler appLogin in the Properties panel.

  5. Click Frame 1 of the UI Components layer.

  6. Drag the following Communication UI components to the Flash stage in a similar location to Figure 17.1. Set the properties of the components as follows:

    ConnectionLight name: connectionLight_mc

    AVPresence name: av_mc, presenter SharedObject: av1

    Chat name: chat_mc

    PeopleList name: peopleList_mc

  7. Click Frame 1 of the Cursor layer.

  8. Drag a Cursor component to the Flash stage next to the ConnectionLight. Remember, this component will be invisible, so don't forget where you put it. Give it the instance name cursor_mc.

  9. Click Frame 1 of the FaceParts layer.

  10. Add in two dynamic text boxes. These will be used to let your users change the text within them.

Now comes the fun part. You will need to collect some graphics, images, or shapes to make this work. Any Flash asset that can be made into a MovieClip will work. The more you have the more fun it will be. The face parts illustrated in Figure 17.1 are available for download as a PC ZIP or Mac HQX package from the book's web site (http://flashcom.PangaeaNewMedia.ca).

Importing Images to the Library

You can do a bulk import with Flash MX when you import directly to the library. To import images and convert them to MovieClips, follow these simple steps:

  1. Click Frame 1 of the FaceParts layer.

  2. Choose File, Import to Library from the Flash MX menu.

  3. Browse your operating system or networked drives for images or artwork you want to use. Select as many as you want. Just remember, you will have to place them all on your Flash stage.

  4. When you have the images in your library, you can now make them MovieClips. To control them with ActionScript, you must first place them on the main Flash stage with instance names.

Tip

If you are comfortable with the attachMovieClip function, you can dynamically use the library assets without going through the MovieClip process.

There are other import options available. Ensure your play head is on the correct frame before you choose any of these other options.

  • Copy and paste. If you use Macromedia Freehand, Adobe Illustrator, or any other graphics program, you can copy and paste vector or raster graphics directly onto the Flash stage.

  • Other Flash documents. You can copy and paste artwork and MovieClips directly from other Flash documents. Simply select the object or the frame, copy it, and then paste it within your document.

  • Drawing tools. You can create objects using the Flash MX drawing tools. Make sure they are grouped together into their own MovieClips. They could even be animated MovieClips just to make it even more interesting.

With your assets now available you must now make them MovieClips. When an imported item becomes a MovieClip, it will inherit the properties and methods of the MovieClip object letting you control it with ActionScript.

  1. Click Frame 1 of the FaceParts layer. (Yes, this keeps repeating itself, because it's important.)

  2. From the library, drag each imported image or asset to the Flash stage.

  3. Convert each asset to a symbol by selecting it and pressing F8 (or Insert, Convert to Symbol). This will invoke a dialog box as in Figure 17.4.

    Figure 17.4. The dialog box that will appear when converting an item to a MovieClip.

  4. It doesn't matter what you name it at this point. It will be the instance name that you will use to control it. As a point of organization, name the clip the same as the instance name. Click OK

  5. Assign the new MovieClip an instance name in the Properties panel. If you have a number of clips, you will need to remember what you called them all, so choose a logical naming convention. These names will be used in an array later, so use a sequential naming convention (mouth1, mouth2, mouth3, and so on).

  6. Repeat Steps 1 through 5 for each asset in your library.

When all your assets have been made into MovieClips with unique instance names, you are then ready for coding.

The only thing you haven't done at this point is add background artwork to the FacesBG layer. Because the artwork is not critical for this tutorial, let's move on to the code layer instead.


Macromedia Flash ActionScript (Frame 1)

The ActionScript used in this tutorial draws on techniques you have seen in earlier chapters. The trickiest part is assigning the event handlers for each MovieClip. Clearly you don't want to write an onPress and onRelease event handler for each MovieClip. Instead, you will use a great looping technique.

The entire Flash ActionScript will be placed on the Actions layer in Frame 1. The ActionScript has been separated into a series of functions to help you follow the flow. The functions are not split, and each step will describe the activity within the function. If certain processes need to be explained within a function, they will be explained in ActionScript comments.

  1. Place your timeline cursor on the Actions layer at Frame 1.

  2. Include the NetDebug Class file so you can monitor activity using the NetConnection Debugger:

    #include "NetDebug.as"

  3. Instantiate the NetConnection object to the local variable myConnection_nc. The connect() method will be called when the user presses the Login button. The ConnectionLight is connected at this point to monitor the connection state. Add the following ActionScript:

    myConnection_nc = new NetConnection();
connectionLight_mc.connect(myConnection_nc);

  4. Define the appLogin method that will be invoked when the user clicks the Login button. This method will invoke the NetConnection connect() method. When the server responds, it will trigger the connection of the SharedObjects and UI comoponents. Add the ActionScript:

    //
// CONNECT THE APPLICATION WHEN THE LOGIN BUTTON IS PRESSED
appLogin = function () {
         myConnection_nc.connect("rtmp://localhost/makingFaces/myInstance", login_txt.
  text);
};

  5. Create a generic onStatus handler to receive messages from the server. This function will monitor for the NetConnection Success code. When it is received, the function knows the server has received the connection request and has invoked the Client object. In other words, it is ready to go. When the function receives the Success code, three functions will be invoked. Add the following ActionScript:

    //
// TRACE TEMPLATE
traceStatus_template = function (info) {
         trace("Level: "+info.level+"   Code: "+info.code);
         if (info.code == "NetConnection.Connect.Success") {
                  UIComponents_init();  // Connect the UI Components
                  SharedObject_init();  // Connect and setup the SharedObject
                  clip_init(); // initialize the MovieClip events
         }
};

  6. Overwrite the onStatus prototype for NetConnection and SharedObject with your generic handler traceStatus_template:

    //
// OVERWRITE THE ONSTATUS PROTOTYPES
NetConnection.prototype.onStatus = traceStatus_template;
SharedObject.prototype.onStatus = traceStatus_template;

    Next, you must create the three functions that the onStatus handler calls when the server responds with a successful connection code.

  7. The UIComponents_init() function connects each UI component you are using once the connection has been accepted. Use this code:

    //
// CONNECT THE UI COMPONENTS
UIComponents_init = function () {
         av_mc.connect(myConnection_nc);
         chat_mc.connect(myConnection_nc);
         cursor_mc.connect(myConnection_nc);
         peopleList_mc.connect(myConnection_nc);
};

  8. Add the SharedObject_init() function to establish and connect the SharedObject:

    //
// CONNECT THE SHARED OBJECT
SharedObject_init = function () {
         this.so = SharedObject.getRemote("kookie", myConnection_nc.uri, false);
         this.so.onSync = function(info) {
                  for (row in info) {
                           trace("** sync["+row+"]: "+info[row].name+"CODE: "+info[row].
  code);
                           trace("** Value: "+so.data[info[0].name].x);
                           if (info[row].code != "success") {
                                    var objID = so.data[info[row].name].id;
                                    var newX = so.data[info[row].name].x;
                                    var newY = so.data[info[row].name].y;
                                    this[clip_array[objID]]._x = newX;
                        this[clip_array[objID]]._y = newY;
                                    this[clip_array[objID]].swapdepths = 0;
                           }
                  }
         };
         this.so.connect(myConnection_nc);
};

    The movie uses SharedObject_init() to move MovieClip objects on your stage when someone else moves it. The onSync handler embedded within this function monitors for a sync code value that is not Success. A Success message is received only when the SharedObject change was made locally. The setProperty methods change the x and y position of the MovieClip on the remote players.

    The onSync code is expanded so you can track what is going on. If you are confused why there is a loop in the onSync handler, remember that an array of objects is always returned to onSync. This is a different type of object than the information objects received by the onStatus handler. The loop will step through each array element in the info object, and check the info.code value for Success. Remember that when a client connects to a SharedObject, it will receive a series of change codes to synchronize it with the data in the SharedObject. Essentially, this loop will reposition every object that has been changed prior to it connecting.

    Within the loop, following the trace actions, the value of the properties, objID, x and y are transferred to a local function variable to make the code easy to follow. Then, using the objID value (which contains the array position of the MovieClip being affected) the name of the MovieClip is used to change the x and y position of the object. This will become clearer in the next step of the tutorial. It is this script that will change the position of the MovieClips on remote computers. Using the swapDepths property, the MovieClip will be positioned in front of all other MovieClips on the main Flash stage.

    Figure 17.5, shows the trace output of a client that is connecting to a session that has already moved pieces around. The figure's output is showing an initial synchronization of six objects and an additional two moves of the mouth1_mc.

    Figure 17.5. The Flash Output window displaying a synchronization event when a client connects to a pre-existing session.

  9. The clip_init() script will make it easy for you to assign event scripts to all the MovieClip face pieces you created. When invoked, this handy script defines an array (clip_array) that contains the instance names of each MovieClip (face part) you created. If you used different MovieClip names, the array values will have to be changed to match. The array will then be looped through and assigned two events and a new property that will identify it in the SharedObject. Add the code:

    //
// INITIALIZE THE MOVIE CLIPS
//   This function will loop through an array of MovieClip names,
//   and dynamically overwrite the onPress and onMouseUp events.
//   It will also set an internal ID number used in the SharedObject

clip_init = function () {
         /* Define the names of MovieClips */
         clip_array = new Array("eye1_mc", "eye2_mc ", "eye3_mc ", "eye4_mc ", "eye5_mc ",
   "eye6_mc ", "eye7_mc ", "nose1_mc ", "nose2_mc ", "mouth1_mc ", "mouth2_mc ", "mouth4_mc
  ", "mouth3_mc ", "nose4_mc ", "eye8_mc ", "eye9_mc ", "brow_mc ");
         /* set the length of the array to a local var */
         var clip_array_LEN = clip_array.length;
         /* loop through the array of names and set each onPress & onMouseUp */
         for (i=0; i<clip_array_LEN; i++) {
                  var mcName = clip_array[i];
                  this[mcName].onPress = MCPress;  // set the onPress event
                  this[mcName].onMouseUp = MCRelease;   // set the onMouseUp event
         this[mcName].id = i; // set an ID number to identify the clip}
};

    You may notice that you've assigned the onPress and the onMouseUp events to variables. To keep the code clean and understandable, these functions are defined outside of this process. The actual functions are listed in the next step. You will also notice the length of the array was transferred into a local variable (clip_array_LEN). You could place the .length method directly in the for loop; however, you will take a performance (speed) hit with that approach. Assigning it outside will increase the speed of the operation.

    When you use the Flash MX debugger, you can look at the clip_array you created (see Figure 17.6). To enable the debugger, you must have the debugger open and use the Debug Movie command (Ctrl+Shift+Enter or Control, Debug Movie).

    Figure 17.6. The Flash MX debugger displays the array object as a tree that reveals the array position and the value.

    The final two functions define the MovieClip events you assigned to the onPress() and onRelease() events in the previous step.

  10. Create the onPress function inside the MCPress variable:

    //
// MOUSE ACTIVITY MONITOR TEMPLATES
// These templates are assigned  in the clip_init()
MCPress = function () {
         this.startDrag(lockCenter);
         this.swapDepths(0);
         this.onMouseMove = function() {
           // write the x,y position to the SharedObject when it is being moved
                  so.data[this._name] = {id:this.id, x:this._x, y:this._y};
         };
};

    This function will use the startDrag() method to pick up the MovieClip and track it with the mouse position. When you do this, the MovieClip arranges itself above everything using the swapDepths() method. It will also set the onMouseMove event. The onMouseMove event is invoked when the mouse is moved. When the mouse is moving, a process will write the current position of the MovieClip to the SharedObject, thus invoking the onSync handler on each connected movie. (This is where the magic happens.)

    The Structure of the SharedObject can be reviewed in the debugger (see Figure 17.7). This shows that four objects have moved, and each has three properties (x, y, and ID).

    Figure 17.7. The Flash MX debugger displays the structure of the SharedObject. This image shows four slots, each with three properties.

  11. Create the onRelease function within the MCRelease variable.

    MCRelease = function () {
         this.stopDrag();
         delete this.onMouseMove};

    This function is invoked when the user releases the mouse button. It will drop the MovieClip using stopDrag(), and it will clear the onMouseMove event.

  12. Your final act will be to ensure the playhead doesn't move by adding the lines:

    //
// CONTROL THE PLAYHEAD
stop();

That's it for the Flash ActionScript. As you can see, it really is not that complex. This application is a great example of the power of the SharedObject Synchronization engine. Think of the data it is tracking. Each time a MovieClip is moved, data is essentially streamed in and out of the server. The server-side script is very straight forward. You are not calling any processes, just requesting a connection.

Server-Side ActionScript (main.asc)

The server-side code is very simple. You need to use acceptConnection and set the username in the UI component framework.

  1. Create a new folder in the FlashCom application folder called makingFaces.

  2. Create a main.asc file and add the following SSAS to it:

    load("components.asc");
application.onConnect =function(newClient,newUserName) {
         application.acceptConnection(newClient);
         // Set the username for the UI componetns framework
         gFrameworkFC.getClientGlobals(newClient).username =newUserName;
}

This application does not draw on very much processing at the server. The bulk of the work is done at the Flash player.


Summary

That's it. You are ready to go with the application and impress all your friends. :-) When you are testing, try to gather many people into the application to experience the stability of the server—and have a good time doing it!


Chapter 18. Build Training and Education: The Virtual Classroom

Application type: Controller-Subscriber

UI components used: Chat, PresentationSWF, MessageBox, ConnectionLight

Flash objects: Camera, Microphone, NetConnection

SSAS objects: Application, Client

Key points: Dynamically Switching a Stream Source

The Virtual Classroom application is a good foundation for an elaborate e-Learning application. This tutorial will only focus on the communication part of e-Learning, but you could extend the application with a testing module, classroom management, or grading.

Figure 18.1. The teacher and student interfaces.

The application itself uses a controller and subscriber model as presented in Chapter 9, "STEP 9: Controller and Subscriber Applications." The interface is simple, but elegant. Remember, the interface should not distract the student from what the teacher is presenting. The exercise is similar to the one you did in Chapter 9, but with one big difference. Where that exercise had audio-only chat using the prebuilt AudioConference component, this application uses a real-time video source switch controlled by the teacher. This switch lets the teacher invite a student to answer a question. You know the trick: You're falling asleep in class, and the teacher catches you and makes you answer a question that you missed while dozing. In this application, a student can "raise her hand" to ask the teacher a question, or the teacher can trigger the student's camera and microphone—sort of like bringing her to the front of the class.


Student User Case Study

Students receive a scheduled time to connect to the virtual classroom by email. At the start of class, a login prompt lets each user type a name and enter the student interface. The server accepts all users as students and enables the student interface (subscriber). The teacher enters a special name in the login field that enables the teacher (speaker) controller interface.

Students are required to have a web camera and microphone working on their computers before connecting to the virtual classroom.

The student interface includes:

  • Presentation controls and a blank area for the presentation.

  • Live video window of the teacher with audio attached.

  • Live local view of the student's camera.

  • Live chat tool to interact with other students during the presentation. (The teacher can disable the chat tool if required.)

  • Information about the class, including the teacher's phone number and email.

  • A window place holder for student video questions. The teacher controls this window and the camera feed being published to it.

The student must pay attention to the lecture because at any time the teacher can force the student's camera and microphone on and place him in front of the class to interact with the teacher.

This application does not evaluate the student or provide archiving and so on.

When the class is over, the student can continue chatting or interacting with the teacher, until the teacher closes the application and disconnects everyone.


Teacher User Case Study

The teacher is responsible for ensuring all students are notified of the upcoming class.

The teacher logs into the virtual classroom using the same interface as the students, but uses a special username (listen2Me) to trigger the teacher screen. When the teacher arrives at the teacher screen, the web camera and microphone are automatically connected and the default presentation is loaded. The teacher can manually load new presentations from within the teacher interface and can control the advancement of the slide presentation.

The teacher interface handles student requests to answer questions asked by the teacher in the video feed or in the Chat window. Accepting a request engages the student's video camera and microphone. The student then appears on everyone's screen in the top-right corner.

Text areas on the screen can be edited by simply clicking on them and reentering the data.

Other teacher controls include:

  • Turning off the student video feed

  • Forcing a student's video feed to the screen

  • Disabling the Chat window

  • Pausing the teacher Video window

  • Closing the virtual classroom

You need to build three interfaces, and there is quite a bit of work to do.


The Interfaces

We'll step quickly through the design process to focus on the scripting later. This section addresses which elements need to be placed where and with what properties. We'll start from the bottom frame and work our way up. Although this tutorial uses background artwork to help with the layout, these graphics are not required and will not be reviewed in this tutorial.

This application requires three interfaces:

  • Login interface

  • Student interface

  • Teacher interface

Each interface will exist on a different frame within a common Flash document. You will build the login screen on Frame 1, the student interface on Frame 10, and the teacher interface (controller) on Frame 20. Much of this application's interfaces will be similar to the ones discussed in Chapter 9, Exercise 9.2. We'll start by setting up the Timeline.

Exercise 18.1: Setting Up the Timeline

The Timeline is used to control the three different interfaces. The student and teacher interfaces share layout elements but have unique elements and ActionScript. The login interface is completely separate. Figure 18.2 shows how your Timeline should look when you are finished.

Figure 18.2. The completed Timeline.

  1. Create nine new layers and name them from top to bottom:

    • Labels

    • Actions

    • Messagebox/Login

    • connectionLight

    • TextPrompts

    • Buttons: Unique

    • Objects: Unique

    • Video Objects

    • Common Objects

  2. Click and drag Frame 30 on the Labels layer and drag down to the bottom to select all layers on Frame 30.

  3. Add frames (F5) to create 30 frames on all layers.

  4. Add keyframes (F7) at Frame 10 on all layers, except on the ConnectionLight layer.

  5. Add keyframes (F7) at Frame 20 on all layers except connectionLight, Video Objects, and Common Object. The bottom two layers should span Frame 20 (see Figure 18.2).

  6. Place three labels in the Labels layer at Frames 10, 20, and 30. Call them Login, Student, and Teacher, respectively.

Your Timeline is now ready for action.

Exercise 18.2: Constructing the Interfaces

This exercise will step you through the construction of three separate interfaces. Each interface will be built at separate frames on the Timeline you setup in the previous exercise.

Step 1: The Login Interface (Frame: 1)

The login screen (see Figure 18.3) is exactly the same as the login screen you built for Chapters 9 and 10, "STEP 10: Lobby Applications." It has a single text input box and a PushButton to call the login process.

Figure 18.3. The login screen.

  1. Place the following elements in the Login layer at Frame 1:

    Text input field: Name: login_txt

    PushButton from the Flash UI Components panel: Label: Login Click Handler: appLogin
Step 2: The Student Interface (Frame: 10)

Building the student interface is as simple as assembling a series of Flash UI components and some dynamic text boxes. The teacher interface uses all the elements you place on this screen, as well, which is the major benefit to using the same Flash document for both interfaces. Use Figure 18.4 as your layout guide.

Figure 18.4. The student interface screen.

  1. Place the Chat UI component on Frame 10 on the Common Objects layer.

  2. On the same frame and layer, place PresentationSWF and set the following:

    Instance Name: presentation_mc

    Width: 508

    Height: 296

    X: 90

    Y: 0

    Note

    The PresentationSWF object uses the file simple_preso.swf as the presentation movie. This SWF file, and its source FLA file, is a sample movie installed with the Flash Communication Server. You can find it within the application folder, sample_broadcast. It is also available on the book's web site at http://flashcom.PangaeaNewMedia.com/.

  3. At Frame 10 on the Video Objects layer, place two Embedded Video objects. Give the first one the following settings:

    Instance Name: student_video

    Width: 90

    Height: 80

    X: 0

    Y: 10

    Give the second Embedded Video object the following settings:

    Instance Name: speaker_video

    Width: 120

    Height: 100

    X: 475

    Y: 15

  4. At Frame 10 on the Objects: Unique layer, which is the student-only layer, place a third Embedded Video object with these settings:

    Instance Name: local_video

    Width: 70

    Height: 60

    X: 15

    Y: 240

  5. On the same frame and layer, place a Message Box from UI Components Set 2 and use the following settings:

    Instance Name: studentPopup

    Width: 370

    Height: 120

    X: 90

    Y: 150

    Title: Video Request Denied

    Message: instructor denied your request

    Visible: false

  6. Still on Frame 10, but on the Buttons: Unique layer, which is also a student-only layer, add a PushButton UI component with these settings:

    Label: raise hand

    Click Handler: askQuestion

  7. Now it's time for the text boxes. On Frame 10's TextPrompts layer, which is student-only, add four dynamic text boxes all with Multiline set to true. Put the first box under the speaker video window and name it teacher_info. Put the second under the student video window and name it student_info. Put the third under the presentation controls and name it course_info. Put the fourth and final dynamic text box between the presentation screen and the Chat window and name it presentation_info.

That's it for the student interface. When everything is active, it should look like Figure 18.5.

Figure 18.5. The final interface as it will appear to the student.

Step 3: The Teacher Interface (Frame: 20)

The teacher interface (see Figure 18.6) is your most complex interface, but really it's not that hard to create. Because we are building both interfaces within the same Flash movie, you can build on top of what you created for the student interface. For the teacher interface, you will reuse all the components you used in the student interface with no additional placement. You will, however, have to add some additional elements to the teacher screen.

Figure 18.6. The teacher interface.

  1. On the Buttons: Unique layer, which is teacher-only, add four PushButton UI components. For the first one, use the following settings:

    Instance Name: studentOff_pb

    Label: Student Off

    Click Handler: student_stop

    For the second one, use:

    Instance Name: studentOn_pb

    Label: Get Student

    Click Handler: student_start

    For the third one, use:

    Instance Name: chatControl_pb

    Label: Disable Chat

    Click Handler: disableChat

    For the fourth one, use:

    Instance Name: camControl_pb

    Label: loadingCamera

    Click Handler: no ClickHandler

  2. In the TextPrompts layer, right-click (or Ctrl-click on the Mac) on Frame 10. Select Copy Frames from the menu. In the same layer, right-click on Frame 20 (teacher-only). Select Paste Frames to copy the placement and the properties of all Text objects.

  3. For each Text object, select Input Text from the Properties window to make the boxes editable. Click the Show Frame and Background toggle in the Properties window to draw a white frame underneath the text. This is a great technique for reusing dynamic text boxes.

  4. Back in Frame 10, add a Message Box from UI Components Set 2 to the MessageBox/Login layer. Use the settings:

    Instance Name: myMessageBox

    Width: 275

    Height: 130

    X: 140

    Y: 120

    Title: Student Question

    Message: A student has requested a question

    Buttons: [DENY,ACCEPT]

    Close Handler: student_start

    Visible: false

That's it for the teacher interface. Use Figure 18.6 to help you with the layout.


The Code

The ActionScript required for this application is a bit more involved than you've seen. The key difference is that there is more communication between the controller and the subscriber.

Messaging between the controller and subscriber movies make up a large part of the script. This is not text messaging between the teacher and student, but one movie controlling the other. As you saw when you built the interface, the teacher has a lot of control over the subscriber interface. Messaging determines the source for the student stream and controls when a student's camera will start and stop. Before jumping into the code, let's first step through some of the elements you will encounter in the script.

The Messages

This application uses messaging over a nonpersistent SharedObject called lecture. The server creates this SharedObject when the application instance loads, so you know it will never be deleted as long as the application instance is running. Broadcast messages are functions calls invoked remotely using the .send() method by other clients connected to the same SharedObject. Broadcast messages are sent to every client that is connected to the Remote SharedObject. If a client does not have the function defined, it will be ignored. The broadcast messages in this application that are invoked from the client or the server are:

  • askQuestion Defined on the teacher interface; invoked from the student interface. Displays a confirm box on the teacher interface invoked by a student requesting the teacher connect to the student's web camera. The teacher accepts or denies the request. Each response invokes a related handler on the clients. Each client receives and handles the request. Because the teacher interface sends the identification of the user making the request, however, the caller is the only one that will respond.

  • startPublishClient Defined on the student interface; invoked from the teacher interface. Invoked each time the broadcast is made, but operates only when a matching client ID is found in the parameter. Its primary operations are to publish the web camera and microphone to a stream called student_source. It also sets the current student's name on every client. The student_source stream is connected by the server to the studentStream being received by all subscribers.

  • denyRequest Defined on the student interface; invoked from the teacher interface. Triggers a message box on the student's interface informing him that his request was denied by the teacher.

  • stopPublishClient Defined on the student interface; invoked from the teacher interface. Stops the publishing streams being sent from the client.

  • loadSWF Defined on the student interface; invoked from the teacher interface. Used by the teacher to change presentations. When invoked, it calls the presentationSWF method to load a new SWF movie.

  • chat_toggle Defined on the student interface; invoked from the teacher interface. Enables or disables the text chat on the student's interface. This handler is not defined in the teacher interface, and will have no affect to the teacher's Chat window.

  • studentRequest Defined on the student interface; invoked from the teacher interface. Called by the teacher to force an unsolicited student's camera to be activated. The student will then be part of the conversation on all connected clients.

  • authenticateUser Defined on the server; invoked from the login interface. Uses the NetConnection, not the SharedObject. It is not invoked with a broadcast message and will expect the server to return a result. It is used to determine the role the user will play in the applications. The options are teacher and student.

These functions are defined in the following exercises. Before you get into the ActionScript, let's first understand how streaming video will be handled in this application.

The Streams

There are three streams used in this application. Every student automatically connects to two streams when they connect. By default there is no source for the studentStream. The streams are:

  • speakerStream Published by the teacher interface. Subscribed to automatically by every student interface connected.

  • studentStream Published by the server. Created by the server upon start up. It retransmits a video stream source determined by the teacher interface. It connects to the student_source stream, which, until the teacher enables it, does not exist. The server waits and then retransmits when the student_source stream becomes available. This is how you will switch what camera the students see.

  • student_source Published by the student on the command of the teacher. Once it is published, the server redistributes it to every connected client, including the teacher interface.

With the streams and the SharedObject functions sorted out, the last element to review before getting into the code is the structure of the SharedObject.

The SharedObject: Lecture

When the server loads, it creates a temporary SharedObject called lecture. This SharedObject has two purposes: to store four slots of information and to act as a transport for the broadcast messages. Figure 18.7 shows the structure of the remote SharedObject in the Flash Debugger. The four slots contain the values used for the text objects surrounding the presentation window. They are:

  • teacher_info Stores the teacher's contact information just below the teacher's video image.

  • course_info Stores the course information for the window just below the presentation controls.

  • presentation_info Stores the information about the current presentation just above the Chat window.

  • presentation_file Stores the current SWF movie presentation.

Figure 18.7. The Debugger tool shows the structure of the data, which is stored as slots inside the remote SharedObject.

These text objects can be changed at anytime by the teacher by simply clicking the text area and editing the content in place. Because they are connected to SharedObjects, a script listens for changes to the text and synchronizes the data change to the students in real time (so don't make a spelling mistake).

Authentication

There is no authentication with this application; it will accept anyone who enters a name. It does use the server to determine what role the user plays. Based on the value of the login, it sets the role to either teacher or student. This information is exchanged with the client using a function defined in the client prototype on the server. Because it is transmitted over the NetConnection, it can receive a return variable from the server.

So that's your primer. To make it simpler for you to step through this code, it has been encapsulated into functions, which in some cases may not be as efficient as possible. The tutorial is focused more on understanding than on efficiency, however.

Exercise 18.3: Building the ActionScript

Step 1: The Initialization ActionScript

You're ready to start coding now. The best place to begin is the initialization scripts for Frame 1.

  1. Place your cursor on Frame 1 of the Actions layer.

  2. Overwrite the onStatus handler prototypes for NetConnection, NetStream, and SharedObject to monitor activity in the Output window. The onStatus template listens for two NetConnection information codes: Success and Closed. When Success is received, the connection has been accepted by the server and the client function, app_init(), is called. If the client becomes disconnected from the server, then the function app_close() is called to clean up. The code you need is:

    onStatusTemplate = function (info) {
      trace("StatusChange: "+info.code);
      if (info.code == "NetConnection.Connect.Success") {
            app_init();
      } else if (info.code == "NetConnection.Connect.Closed") {
            app_close();
      }
};
NetConnection.prototype.onStatus = onStatusTemplate;
NetStream.prototype.onStatus = onStatusTemplate;
SharedObject.prototype.onStatus = onStatusTemplate;

  3. Initialize a global object called Session. Session will be used to store global properties, such as the username and pending users. Set up the NetConnection object and the connection light with the following code:

    //
// INITIALIZE THE CLIENT
Session = new Object();
myConnection_nc = new NetConnection();
connectionLight_mc.connect(myConnection_nc);

  4. Create the appLogin() function used by the Login button. This function will call the connect() method of the NetConnection and create a username property in the Session object. Add the following code:

    //
// LOCAL APPLICATION FUNCTION HANDLERS
appLogin = function () {
      // Login Button was clicked, make the connection with the server
      myConnection_nc.connect("rtmp://localhost/chapter18/myInstance");
      // setup a session object that will contain information about this user
      Session = ({username:login_txt.text});
};

  5. Create the function called by the onStatus handler when the NetConnection code Success is received. When called, this function, app_init(), calls a function on the server named authenticateUser and defined in the Client object. This method will return a value, so a Result object (serverRet) waits for the server to respond. Add the following code:

    //
// APP_INIT is called when the server returns a "NetConnection.Connect.Success" code

app_init = function () {
      trace(" ** Connected :-)");
      trace(" ** User set to: "+Session.username+".  Authenticating user...");
      // call the authenticateUser function on the server
      myConnection_nc.call("authenticateUser", new serverRet(), Session.username);
};

  6. Create serverRet(), the Result object to handle the returned values from the server. Create an onResult event method inside the Return object that will be invoked when the server returns the call. The server returns either teacher or student for the value. This value will immediately be used to move the play head to the required position. When the play head moves, the interface changes. Add the following code:

    //
// Global Server method handler
serverRet = function () {
      // Handle server returns
      this.onResult = function(ret) {
            trace(" ** :-) Server returned: "+ret);
            trace("**  The User has been assigned");
                  Session.userRole = ret;
                  _root.gotoAndPlay(ret);
      };
};

  7. Create app_close(), a handler for when the NetConnection terminates unexpectedly. This function is called when the NetConnection onStatus handler receives a connect.Close code. The function returns the user to the login prompt. You could also use this function with a logout button:

    //
// ** APP_CLOSE
app_close = function () {
      if (myConnection_nc.isConnected) {
            myConnection_nc.close();
      }
      _root.gotoAndStop(1);
};

  8. Declare the function init_SharedObject(). It will not be invoked until the user enters the specific interface. We wait to connect the SharedObject so that when it connects, the synchronization process updates any changed screen information.

    The function is responsible for connecting to the remote SharedObject and building the onSync handler. The onSync handler will loop through the information array when it is received and update any data that needs updating. The code for SharedObject_init() is:

    //
// CONNECT THE SHAREDOBJECT
// The SharedObject is initiated when the user enters the interface
SharedObject_init = function () {
      this.so = SharedObject.getRemote("lecture", myConnection_nc.uri, false);
      this.so.onSync = function(info) {
            trace("syncing");
            for (row in info) {
                  trace("** sync["+row+"]: "+info[row].name+"CODE: "+info[row].code);
                  trace("** Value: "+so.data[info[row].name]);
                  if (info[row].code != "success") {
                        trace("set it");
                        set(info[row].name+".text", so.data[info[row].name]);
                        [info[row].name].text = so.data[info[row].name];
                        course_info.text = so.data[info[row].name];
                  }
            }
      };
      this.so.connect(myConnection_nc);
};

  9. The last line of code stops the play head from advancing. Add the following code:

    //
// PLAYHEAD CONTROL
stop();

That's it for the initialization scripts. Let's move on to the student and teacher scripts.

Step 2: Build the Student ActionScript

The following student script executes only when the play head passes over it or stops on it. It will not be invoked when ActionScript jumps (gotoAndPlay) the play head from the login screen to Frame 20.

Like the script on Frame 1, this script has been encapsulated within functions so you can easily follow it.

  1. Click on Frame 10 on the Actions layer.

  2. Add the init_Student() function to initialize the Communication UI components, the SharedObject, and the streams. The streams_init function is defined in the next step, and the SharedObject_init function was defined in Frame 1. This function is called from the init_Student() function:

    //
// CONNECT THE UI COMPONENTS AND THE LOCAL CAMERA FEED
init_Student = function () {
      _global.speakerMode = false;
      PeopleList_mc.connect(myConnection_nc);
      presentation_mc.connect(myConnection_nc);
      chat_mc.connect(myConnection_nc);
      init_SharedObject();
      init_Streams();
};

    You will notice a _global variable set in this function. The presentationSWF communication component monitors the _global variable speakerMode. The Boolean value of this variable sets the presentationSWF component into a Speaker mode. Speaker mode allows the user to advance the presentation, synchronizing the connected clients.

  3. Add the code for init_Streams() to initialize two incoming streams to the student application. Also, attach the camera to the local Video object to be used for camera adjustment. The init_Streams() function is called from the init_Student() function:

    //
// ENABLE THE RECEIVING STREAMS
// Enable the Speaker feed (from the Teacher)
init_Streams = function () {
      // Attach the local camera feed to the local_video object.
      local_video.attachVideo(Camera.get());

      // Enable the Speaker Feed
      speaker_ns = new NetStream(myConnection_nc);
      speaker_video.attachVideo(speaker_ns);
      speaker_ns.play("speakerStream");

      // Enable the Student Feed
      student_ns = new NetStream(myConnection_nc);
      student_video.attachVideo(student_ns);
      student_ns.play("studentStream");
      myPublish_ns = new NetStream(myConnection_nc);
};

  4. Create a function that will be invoked when the user clicks the Ask Question button. When invoked it will broadcast a message to the SharedObject subscribers to call the studentRequest function. The only client that will have this function enabled is the teacher. It will pop up a message box informing the teacher that the student would like to engage the conversation. The code you need is:

    // SHAREDOBJECT BROADCASTERS
askQuestion = function () {
      so.send("studentRequest", Session.username);
};

  5. Create a handler for the SharedObject broadcast startPublishClient. This broadcast will contain a property with the student's name who requested to be connected. Use this property to determine if the client should act or not. If the studentName matches the name stored in the session property, then the message is for you. Think of it like a mail carrier. The broadcast has an address and the mail carrier will not let anyone handle the letter unless it is addressed to them. Add the following code:

    //
// THE SHAREDOBJECT BROADCAST HANDLERS
so.startPublishClient = function(studentName) {
      if (studentName == Session.userName) {
            // Student video connect has been accepted
            Session.isStreaming = true;
            trace("I am now streaming "+studentName);
            // Start the Publish stream
            myPublish_ns.attachAudio(Microphone.get());
            myPublish_ns.attachVideo(Camera.get());
            myPublish_ns.publish("student_source");
      } else {
            trace("notMe!");
      }
      student_info_txt.text = studentName;
};

    If the message engages the process, a session property, isStreaming, is set to true and a new NetStream object is created to publish the student's camera. The stream name will be student_source, which is what the server uses for the outgoing feed, studentStream. As soon as the video is published, the server picks it up and redirects it to the studentStream.

  6. Create a function to handle the broadcast message stopPublishClient. This function also uses a filter, but this time it will look at the Session.isStreaming property. If it is set to true, then the process continues and closes the stream being published. Remember, only one student can be publishing at any one time. The server script always broadcasts this function before broadcasting the startPublishClient() function. The code is:

    // stop publishing handler
so.stopPublishClient = function(studentName) {
      if (Session.isStreaming) {
            trace("I have stopped streaming");
            // shutdown the stream
            myPublish_ns.
close();
      }
};

  7. Create a function to handle the broadcast message, loadSWF. This function will control the presentationSWF component on all student interfaces. When the teacher broadcasts this, it passes the value to the presentationSWF function loadSWF() to change the presentation source file. Add the following code:

    // change SWF movie handler
so.loadSWF = function(SWFtoLoad) {
      presentation_mc.loadSWF(SWFtoLoad);
};

  8. Create a function to handle the broadcast message, denyRequest. This function will be invoked by the teacher if the request for participation is denied. A message box appears informing the student the request was denied. Add the following code:

    // Handle a denied question request
so.denyRequest = function(studentName) {
      if (studentName == Session.userName) {
            studentPopup._visible = true;
            studentPopup.setMessage = "Your Video Request was Denied";
      }
};

  9. Create a function to handle the broadcast message chat_toggle. This function will serve as two functions in one. The teacher interface will broadcast this call with a Boolean value attached (true or false). This value can be directly used to change the visibility of the chat component. The code you need is:

  10. // toggle the visibility of the Chat component
so.chat_toggle = function(toggle) {
      chat_mc._visible = toggle;
};

  11. Finally, your last script will be one that starts a chain reaction that fires the whole thing up. At the bottom of all this script, call the function init_Student() and watch everything light up! Also, place a stop()command to ensure the playhead doesn't move:

    //
// PLAYHEAD CONTROL
init_Student();
stop();

Now, on to Frame 20.

Step 3: Build the Teacher ActionScript

The teacher scripts contain many of the same processes as the student scripts. Where the student has more scripts attached to the SharedObject, the teacher script has more calls to the methods.

  1. Connect the UI components, and set _global.speakermode to true. Call the functions, enableCamera(), init_SharedObject(), and enableStudentStream():

    //
// CONNECT THE UI COMPONENTS AND THE LOCAL CAMERA FEED
init_Teacher = function () {
      _global.speakerMode = true;
      peopleList_mc.connect(myConnection_nc);
      presentation_mc.connect(myConnection_nc);
      chat_mc.connect(myConnection_nc);
      // invoke the initialization methods
      init_SharedObject();
      init_Streams()
      enableCamera();
};

  2. Create the init_Streams() function to subscribe to the incoming studentStream:

    //
// ENABLE THE STUDENT STREAM
init_Streams() = function () {
      student_ns = new NetStream(myConnection_nc);
      student_video.attachVideo(student_ns);
      student_ns.play("studentStream");
      // Call to enable the local camera during the initialization phase
};

  3. Create the enableCamera() function to connect the camera and microphone to a NetStream and start publishing them as speakerStream. This function will be called beyond just initialization. It is registered to the disable camera button that will enable and disable the speakerStream. The code you need is:

    //
// PUBLISH THE SPEAKER (TEACHER) STREAM
enableCamera = function () {
      speaker_ns = new NetStream(myConnection_nc);
      speaker_ns.attachVideo(Camera.get());
      speaker_ns.attachAudio(Microphone.get());
      speaker_ns.publish("speakerStream");
      // Allow the teacher to see a camera monitor for positioning
      speaker_video.attachVideo(Camera.get());
      // Set the camera control button to disable mode
      camControl_pb.setLabel("Disable Camera");
      camControl_pb.setClickHandler("disableCamera");
};

  4. The function turns off the publication stream and sets the Camera control button to an enable state. Students who are connected will see a still image of the last frame of transmission. Add the following code:

    disableCamera = function () {
      speaker_ns.close();
      camControl_pb.setLabel("Enable Camera");
      camControl_pb.setClickHandler("enableCamera");
};

  5. Create a generic listener for the three text areas of the screen that the teacher can edit:

    //
// SHAREDOBJECT TEXT MONITOR
textOnChanged = function () {
      trace(this._name);
      so.data[this._name] = this.text; };

    The text fields in the teacher's interface are actually input boxes, meaning that the teacher can change the text within them. To make a more fluid interface, with less buttons, this listener will invoke the onChanged handler of the Text object. When the teacher changes any data within the input boxes, the changes will be saved to the SharedObject. Remember what happens when you change data in the SharedObject? The onSync event fires and informs all the connections that the data has changed. The onSync handler you build in Frame 1 updates the text fields at the command of the SharedObject.

  6. Overwrite the default onChanged handler for the three text fields with the new and improved onChanged handler you just built:

    teacher_info.onChanged = textOnChanged;
course_info.onChanged = textOnChanged;
presentation_info.onChanged = textOnChanged;

    See the power of building dynamic scripts? If the generic handler was coded in such a way that it could not be easily propagated, then you would have three times as much code.

  7. Create a handler for the studentRequest broadcast. This process will make the messageBox visible and change the message within it. The broadcaster sent the name of its user with the message. This name will be your identifier to send back if the request was accepted or denied. It will also assign the name of the student as the value of the Session.pendingStudent property.

    The student script did not include this function, so when this message is broadcast over the SharedObject, the only interface that is listening will be the teacher interface. The code you need is:

    //
//  SHAREDOBJECT BROADCAST HANDLERS
so.studentRequest = function(studentName) {
      trace("studentRequest: "+studentName);
      Session.pendingStudent = studentName;
      myMessageBox._visible = true;
      myMessageBox.setTitle = "Request from "+studentName;
      myMessageBox.setMessage = "Please Answer";
};

  8. Create two chat functions to broadcast messages (chat_toggle) for enabling or disabling the Chat window on the student interface:

    //
// CHAT ENABLERS
disableChat = function () {
      so.send("chat_toggle", false);
      chatControl_pb.setLabel("Enable Chat");
      chatControl_pb.setClickHandler("enableChat");
};
enableChat = function () {
      so.send("chat_toggle", true);
      chatControl_pb.setLabel("Disable Chat");
      chatControl_pb.setClickHandler("disableChat");
};

  9. Create two functions to broadcast the stopPublishClient and the startPublishClient messages. These messages will invoke the respective handlers you created in the student script. The handlers are responsible for starting and stopping the publishing stream on the student's interface. Add the following code:

    //
// STREAM ENABLERS
student_start = function (messageBox, buttonIndex) {
      if (buttonIndex == 1) {
            // Accept button was pressed
            trace("mb: "+messageBox+"  bi: "+buttonIndex);
            trace("start Student: "+Session.pendingStudent);
            so.send("stopPublishClient");
            so.send("startPublishClient", Session.pendingStudent);
            student_info_txt.text = Session.pendingStudent;
      } else {
            so.send("denyRequest", Session.pendingStudent);
            trace("denied Student "+Session.pendingStudent);
      }
};
//
// STREAM KILLER
student_stop = function () {
      trace("stop Student");
      so.send("stopPublishClient");
};

  10. Invoke the init_Teacher method to initialize the teacher interface and place a stop() command to ensure the play head doesn't move:

    //
// PLAY HEAD CONTROL
init_Teacher();
stop();

That's it for the Flash scripts. There is a lot going on in this tutorial with plenty of useful techniques you can use to take your applications one step further.

Exercise 18.4: Building the Server-Side ActionScript (main.asc)

With teacher and student scripts finished, you need the server scripts. The server is not used to process very much with this application. It has four roles:

  • Accept all incoming connections

  • Initialize the SharedObject

  • Publish the studentStream

  • Determine the user's role

The server scripts are much less complex than the Flash scripts you just worked on.

  1. Create a new folder in the FlashCom/applications folder; name it makingFaces.

  2. Create a new main.asc file within the makingFaces folder.

  3. Load the UI Components server-side file:

    load("components.asc");

  4. Create an onAppStart event to create a SharedObject and publish the studentStream:

    // INITIALIZE THE APPLICATION
application.onAppStart = function() {
      SharedObject_init();
      studentStream_ns = Stream.get("studentStream");
      studentStream_ns.play("student_source");
};

  5. Create the onConnect event:

    //
// APPLICATION CONNECT
application.onConnect = function(theClient) {
      //Accept the connection from the user.
      application.acceptConnection(theClient);
      trace("Room ID List: "+this.name);
};

    This event will be used to accept the connection and return the status code NetConnection.connect.success, which the script must find before moving forward.

  6. Create a new Prototype method for the Client object:

    //
// ADD A NEW PROTOTYPE FUNCTION
Client.prototype.authenticateUser = function(username) {
      trace("Called from Client");
      if (username == "Kevin") {
            clientRole = "teacher";
      } else {
            clientRole = "student";
      }
      trace("Role: "+clientRole);
      //Set the global user name with the user name passed into this function.
      gFrameworkFC.getClientGlobals(this).username = username+"_"+clientRole;
      return clientRole;
};

    After the server accepts the connection, this method will be called by the client. Its primary responsibility is to review the value of the username supplied by the user and determine if the client is a teacher or a student. It makes the decision and passes the value back to the client. The UI component user login also occurs within this script. It is done here because we want to identify the user visually with the suffix (student or teacher). This value will be displayed in the Chat window.

  7. Add the function called from the onAppStart method to set up the SharedObject:

    //
// SHAREDOBJECTS
SharedObject_init = function () {
      server_so = SharedObject.get("lecture", false);
      server_so.setProperty("teacher_info", "not set");
      server_so.setProperty("course_info", "not set");
      server_so.setProperty("presentation_info", "not set");
      server_so.setProperty("presentation_file", "simple_preso.swf");
      trace("sharedObject inited");
      var test = server_so.getProperty("teacher_info");
      trace("simpleProperty: "+server_so.getProperty("presentation_file"));
};

    The SharedObject is created and reset to default values. As a simple test, it reads data from the SharedObject and returns it in a trace.

Now you can fully test your complete application. This project was a large one, but I am sure you will be happy with it.


Summary

As mentioned earlier, you can do a lot more with an application like this. The example is not a perfect application, but it will give you enough to get you moving in the right direction. For example, you could extend it to a lobby application to handle multiple classes simultaneously.

That sums it up for the tutorials for this book. Remember, all applications developed in this book are available online on the book's web site (http://flashcom.PangaeaNewMedia.ca/). Watch this site and the Designer Developer center on Macromedia.com (http://www.macromedia.com/desdev/mx/flashcom/) for additional tutorials from me, as well.

The book's appendixes contain five quick reference guides giving you a summary of ActionScript objects for the server, Flash, and the UI components. Be sure to review Appendix E,"Useful ActionScript Templates Quick Reference," for some very handy code snippets.


Appendix IV: Appendixes: Quick Reference Guides

A Server-Side Objects Quick Reference

B Macromedia Flash ActionScript Objects Quick Reference

C Information Objects (Server and Client) Quick Reference

D Macromedia Flash UI Component Objects Quick Reference

E Useful ActionScript Templates Quick Reference


Appendix A. Server-Side Objects Quick Reference

    Application Object

    Client Object

    NetConnection Object

    NetServices Object (Macromedia Flash Remoting MX)

    RecordSet Object

    SharedObject Object

    Stream Object


Application Object

The Application object operates under the application instance. Variables, functions, and objects defined within this object are available to every client that connects to a specific instance. Application objects within other instances are not accessible.

Application Methods

The application methods are described in the following sections.

application.acceptConnection(clientObj)

Accepts incoming connection requests from Communication clients. Clients cannot access resources until this method is run.

ClientObj is the client URI requesting access.

application.clearSharedObjects(soPath);

Deletes persistent and temporary SharedObjects from the instance it was called from.

soPath The SharedObject name and path (myPath/myObject).

application.clearStreams(streamPath);

Removes all publish and subscription streams from all clients and servers within the instance it was called from.

streamPath The Stream object name and path (myPath/myStream).

application.disconnect(clientObj)

Disconnects the client from the application instance.

clientObj The name of the active client (Macromedia Flash player) to disconnect.

application.registerClass(className, constructor)

Allows a constructor to be registered or unregistered within the application instance. This is called during deserialization.

className | The name of the Class to be registered or unregistered.
constructor | The object's constructor function. This function must be the same name as the class name.

application.registerProxy(methodName, proxyConnection [, proxyMethodName])

Redirects a method request to a NetConnection or a client method proxy.

methodName | The method to be redirected.
proxyConnection | The Client or NetConnection object that contains the proxied method. Use a NULL value to unregister.
proxyMethodName | An alternate method name within the proxied object.

application.rejectConnection(clientObj, errObj)

Rejects incoming connection requests from Communication clients. Clients cannot access any instance resources.

ClientObj | The client URI requesting access.
errObj | Used to send an object to the client's onStatus handler.

Application Properties

application.clients returns an object containing a list of all clients connected to the application instance.

application.name returns the current application instance name.

application.server returns the current server version and platform.

Application Events

application.onAppStart is invoked by an application instance, which is loaded by a client request or the App Inspector.

application.onAppStop is invoked when the application is shut down or unloaded from the server.

application.onConnect is invoked by a client's NetConnection.connect request. This method is used to handle the acceptConnection method.

application.onDisconnect is invoked by a client's NetConnection.close method, or if the client's connection is broken or the Flash movie is shut down or reloaded.

application.onStatus is invoked internally when a method or server-side ActionScript (SSAS) produces an error.


Client Object

The Client object is instantiated by the application.onConnect() method. Each Communication client has a unique object of methods and properties that can be accessed by the server or the client. The Class can be extended with additional properties and methods. Each property is related specifically to the connected client. Client instances are limited only by the license of the server.

Client Methods

The client methods are as follows:

Client.call(methodName, [resultObj, [p1, …, pN]])

From SSAS, you can call methods on the client that were created by client ActionScript within in the NetConnection object.

methodName | The name of the method defined by the client.
resultObj | The object that will handle properties returned to SSAS by the client. The result object should have two methods (onStatus and onResult).
p1, ..., pN | Optional parameters required by the custom method.

Client.getBandwidthLimit(iDirection)

Returns the maximum one-way communication bandwidth value in bytes between client and server.

iDirection A value of 1 returns the bandwidth from server to client. A value of 0 returns the bandwidth value from client to server.

Client.__resolve(propName)

This method is called when a client calls a method that does not exist. You must overwrite it to handle the error.

propName The name of the method called.

Client.setBandwidthLimit(iServerToClient, iClientToServer)

Defines the maximum bandwidth resources for both directions that a Client can consume. Set a value of 0 in either parameter to not change the current bandwidth setting.

iserverToClient | Maximum bandwidth value from server to client.
iClientToServer | Maximum bandwidth value from client to server.

Client Properties

Client.agent returns the Flash version and platform of the client.

Client.IP returns the IP address of the client computer.

Client.readaccess sets the "read" and listen security access level (or folder) for SharedObjects and streams. Clients with no access to a resource will not receive onSync events from SharedObjects.

Client.referrer returns the URL of the client that originated the connection. An embedded SWF file returns the URL of the page it is embedded in.

Client.writeaccess sets the "read" and listen security access level (or folder) for SharedObjects and streams.

Client Events

Client."commandName"([p1, …, pN])

SSAS methods that can be called remotely by the Flash player or connected server using the NetConnection.call() method.

p1, ..., pN Custom parameters sent by the client to this server method.


NetConnection Object

The NetConnection object enables bi-directional communication using the RTMP protocol between two application instances on the same server or on different servers. This server-side object operates similar to the client-side NetConnection object. It cannot connect with a Flash player. This appendix only represents the methods that are unique to the server. Please refer to NetConnection in Appendix B,"Flash ActionScript Objects Quick Reference."

Unique SSAS NetConnection Object Methods

Unique SSAS NetConnection methods are described in the following sections.

myNetConn.addHeader(name, mustUnderstand, object)

Sets the HTTP context header for an AMF packet over the NetConnection.

name | The ActionScript object name identifying the header.
mustUnderstand | A Boolean value; when set to true, the server is forced to process the header before the message.
object | An ActionScript object.


NetServices Object (Macromedia Flash Remoting MX)

See the "NetServices" entry in Appendix B.


RecordSet Object

See the "RecordSet" entry in Appendix B.


SharedObject Object

The SharedObject is a programming model that allows you to share data between Communication Server clients. SharedObjects can be temporary or persistent. If they are temporary, they are destroyed when the last client or the server has disconnected from the application. SharedObjects send synchronization messages to all connections notifying of change. These objects can be created by the server or by a client, based on the Client permissions. This object can be used by the server to maintain a SharedObject or connect to a Remote SharedObject existing on another server.

To enable Code Hints and Code Completion in Macromedia Dreamweaver MX, use the suffix _so in the name of the SharedObject variable.

SharedObject Methods

The SSAS SharedObject methods are described next:

SharedObject.clear()

Removes all data slots from a persistent SharedObject and returns a "clear" code to all clients subscribed.

SharedObject.close()

Deletes the SharedObject instance, or unsubscribes a SharedObject. The server no longer receives onSync events, but clients that are still subscribed to it still have access.

SharedObject.flush()

Forces an internal "memory" version of a persistent SharedObject to the hard disk. This method is also invoked when all connections to the SharedObject are closed, or the instance is unloaded.

SharedObject.get(name, boolPersist [, netConnection])

Use this function to instantiate the SharedObject and determine the SharedObject to connect to or create. This function can also set up a proxied SharedObject through a NetConnection.

name | The name of the new SharedObject instance.
boolPersist | A Boolean value: A value of "true" accesses or creates a persistent SharedObject; false accesses a temporary SharedObject.
netConnection | The connection to a remote server to proxy a remote SharedObject.

SharedObject.getProperty(name)

Returns the value of a SharedObject slot. This is achieved on the client by accessing the data property.

name The name of the data property or slot to return.

SharedObject.getPropertyNames()

Returns an array of property names slotted to the SharedObject.

SharedObject.lock()

Restricts clients from writing to a SharedObject and suppresses any onSync notifications. OnSync notifications are batched until the object is unlocked.

SharedObject.purge(version)

A cleanup tool that removes all deleted properties that are older than the version declared in the parameter.

version A SharedObject version number.

SharedObject.send(methodName, [p1, …, pN])

Calls a method defined on the client in the SharedObject instance.

methodName | The name of the client method to call.
p1, ..., pN | Custom parameters sent by the client to this server method.

SharedObject.setProperty(name, value)

Set the value of an existing or new SharedObject property.

name | The target property name.
value | A new ActionScript variable. It can include objects, arrays, or any other valid ActionScript type.

SharedObject.size()

Returns an integer value of the total properties active within a SharedObject.

SharedObject.unlock()

Releases a SharedObject lock. When this method is called, all changes that occurred during the lock are sent to all subscribed clients.

SharedObject Properties

SharedObject.name returns the name of the current SharedObject.

SharedObject.resyncDepth sets an integer value to indicate when deleted properties of a SharedObject are purged.

SharedObject.version returns the active version number of the SharedObject.

SharedObject Events

SharedObject."commandName"([p1, ..., pN]) SSAS methods can be set within a SharedObject instance to handle broadcast messages sent from subscribed clients using the .send method.

p1, ..., pN Custom parameters sent to the client function.

SharedObject.onStatus is used to handle status changes of the SharedObject. Status changes contain information objects with code and level properties. For a complete list of values, refer to Appendix D,"Flash UI Components Quick Reference," for a list of all Information Objects related to the SharedObject.

SharedObject.onsync is invoked on every subscriber to the SharedObject when SharedObject properties change. The event returns an array of objects containing information on any changes to a SharedObject property.


Stream Object

The Stream object gives you control over all streams in the Application instance. This object lets you chain servers together to increase user and bandwidth capacity. It also allows you to create play lists, or control the source of any stream. A stream is a one-way flow of data over a NetConnection.

To enable Code Hints and Code Completion in Dreamweaver MX, use the suffix _stream in the name of the SharedObject variable.

Stream Methods

The Stream methods are as follows:

Stream.clear()

Removes a recorded stream (FLV) file created by either the server or a client from the application instance.

Stream.get(name)

Creates or references a stream by name. This method also insatiates the Stream object to your ActionScript variable.

name The name of the stream to create or access.

Stream.length(name)

Returns the length (in seconds) of a pre-recorded stream (FLV). You can use this method without the .get method to return the length of a pre-recorded stream that is not being accessed.

name The name of the FLV file (without the FLV extension).

Stream.play(streamName, [startTime, length, reset, remoteConnection])

The Play command publishes a single recorded stream, or can publish a live stream from a local or remote source. Multiple play methods can be strung together to create a play list.

streamName | The live or pre-recorded (FLV) stream to publish.
startTime | An integer referencing the playback start position in seconds.
length | An integer defining the length of play in seconds. A value of (-1) publishes a live stream as long as it exists.
reset | A Boolean value; when true, it resets the stream.
remoteConnection | Used to access streams in other application instances, or on remote communication servers. This can be used for "chaining" servers together.

Stream.record(record|append|false)

Records the stream to an FLV file. The contents of the stream are determined by a series of play methods. This stream can be used later for playback. The name of the FLV file is determined by the .get method.

record (flag) | Overwrites any FLV file with the same name.
append (flag) | Appends any FLV file with the same name.
false (flag) | Stops recording.

Stream.send(handlerName, [p1, …, pN])

Used to broadcast a message to all subscribers of the stream. This method invokes functions defined in the stream instance on each subscribed client.

handlerName | Call a custom function defined inside the stream (or NetStream) Object in client-side ActionScript.
p1, ..., pN | Custom parameters sent by the server to all stream subscribers.

stream.setBufferTime(seconds)

Allocates the amount of memory to handle pre-loading of a stream before publishing (playing). This command sends a message to the stream publisher source that the size has been changed.

seconds The amount of time to reserve for buffering.

Stream Properties

stream.buffertime returns the length of time in seconds that a stream will be stored before playing begins.

Stream.name returns the unique string used for a live stream.

Stream Event

Stream.onStatus invoked when the status of the subscribed stream changes.


Appendix B. Macromedia Flash ActionScript Objects Quick Reference

    Camera Object

    Microphone Object

    NetConnection Object

    NetServices Object

    NetStream Object

    RecordSet Object

    SharedObject Object

    Video Object


Camera Object

The Camera object controls access to most video sources attached to a client's computer. The Camera object controls capture settings including frame size, frame rate, and bandwidth. You can also set the Camera to trigger an event when it detects motion (or no motion). Macromedia Flash Communication Server is required to record or transmit the video source to other Flash clients; however, the Camera object can be accessed locally without the server.

The camera is enabled using the Camera.get() method. To enable Code Hints and Code Completion in Macromedia Flash MX ActionScript Editor, use the suffix _cam in the name of the Camera variable.

Camera Methods

Camera.get([index])

Captures the camera feed and assigns it to an embedded video object or a NetStream. You can quickly access the camera feed using attachVideo.

[index] The integer number identifying an individual camera in a multicamera environment. The number is determined by the Camera.names property. To select the default camera, omit this parameter.

Camera.setKeyFrameInterval(keyframeInterval)

Overrides the video compression algorithm by setting a different keyframe rate. This will allow you to adjust the quality and bandwidth required by the video feed. Keyframes are uncompressed frames embedded within the video. The video compressor interpolates the visual difference between keyframes to re-create the frames between the keyframes. The default value is 15 frames.

keyframeInterval The number of full video frames to capture per second. The lower the value, the higher the quality of the video and the larger the file size.

Camera.setLoopback(compressLocalStream)

Views the camera feed as it will be sent to Flash Communication Server. Enabling this loop back will engage the video compressor.

compressLocalStream A Boolean value. When set to true, it displays the compressed version of the video locally.

Camera.setMode(width, height, fps [,favorSize])

Defines the camera capture driver settings. These settings will increase/decrease bandwidth and quality.

width | The capture width; default value is 160.
height | The capture height; default value is 120.
fps | The capture frames per second; default value is 15.
favorSize | A Boolean value. When set to true, it specifies to the camera how to handle the capture settings, if the camera doesn't support the sizes natively.

Camera.setMotionLevel(sensitivity [, timeout])

Sets the motion sensitivity, or how much motion would be required to trigger the Camera.onActivity event.

sensitivity | The motion sensitivity value from 0 to 100, 100 being highest sensitivity; default value is 50.
timeout | The length of time in milliseconds of no motion before setting the Camera.onActivity event to false; default value is 2000 (2 sec).

Camera.setQuality(bandwidth, frameQuality)

Sets the maximum bandwidth and frame quality the camera source can consume when publishing to Flash Communication Server.

bandwidth | The bandwidth limit the camera can consume. A setting of 0 supplies the maximum bandwidth available; default value is 16384.
frameQuality | The amount of video compression applied to each frame. The default value is 0 for a variable compression rate as per the bandwidth available. The quality range is from 1 (most compression and lowest quality) to 100 (least compression and highest quality).

Camera Properties

Camera.activityLevel returns the amount of motion being received by the camera.

Camera.bandwidth returns the bandwidth limit allocated by the setQuality method.

Camera.currentFPS returns the rate, in frames per second, at which the camera is currently capturing.

Camera.height returns the current frame height being captured by the camera. To set the height, use Camera.setMode.

Camera.index returns the index of the camera being used.

Camera.keyFrameInterval returns which frames are sent uncompressed. This can be set using Camera.setKeyFrameInterval.

Camera.loopBack returns a Boolean value. A value of true is returned if the video output is filtered through the internal video compressor.

Camera.motionLevel returns the motion sensitivity value of the camera. This is set using Camera.setMotionLevel.

Camera.motionTimeOut returns the timeout value, in milliseconds, when the camera will trigger the Camera.onActivity event with a false value. This indicates there is no motion in front of the camera.

Camera.muted returns a Boolean value. A value of false indicates the client has not allowed camera access when prompted by the Flash player Privacy Settings panel.

Camera.name returns the manufacturer's name of the current camera.

Camera.names returns an array of strings containing the names of all camera sources available to the Flash player. This will not invoke the Privacy Settings panel.

Camera.Quality returns the amount of compression being applied to the outgoing camera feed. This can be set using Camera.setQuality.

Camera.width returns the current frame width being captured by the camera. To set the width, use Camera.setMode.

Camera Events

Camera.onActivity is invoked when motion occurs or stops occurring in the camera's range of view. This event can be controlled using Camera.setMotion.

Camera.onStatus is invoked when the status of the camera changes. The status will change only if the user denies camera access in the Flash player Privacy panel. This event will receive a Camera Information object detailed in Appendix C,"Information Objects (Server and Client) Quick Reference."


Microphone Object

The Microphone object controls access to the microphone input attached to a client's computer. The Microphone object controls capture settings, including sample and gain. You can also set the microphone to trigger events when it detects sound (or silence). The Flash Communication Server is required to record or transmit the microphone source to other Flash clients; however, the Microphone object can be accessed locally without the server.

The Microphone object is enabled using the Microphone.get() method. To enable Code Hints and Code Completion in the Flash MX ActionScript Editor, use the suffix _mic in the name of the Microphone variable.

Microphone Methods

Microphone.get([index])

Captures the microphone feed and assigns it to a MovieClip object or a NetStream. You can quickly access the microphone feed using attachAudio.

[index] The integer number identifying an individual microphone in a multiple microphone environment. The number is determined by the Microphone.names property. If there is only one microphone, omit this parameter.

Microphone.setGain(gain)

Sets the amount of gain (or volume increase) to apply to the microphone.

gain A value that determines the amount of volume to add to the microphone source. The valid range is 0 (silence) to 100 (maximum record volume). This setting can be changed by the user in the Flash player's Microphone Settings panel.

Microphone.setRate(kHz)

Sets the frequency (or sample rate) in kilohertz (kHz) of the sound capture driver.

kHz Values can be 5, 8, 11, 22, or 44 only. The default is 8kHz. 44 is equivalent to CD-quality sound, but requires more bandwidth to distribute.

Microphone.setSilenceLevel(level [, timeout])

Sets the sound sensitivity or how much sound is required to trigger the Microphone.onActivity event.

sensitivity | The sound sensitivity value from 0 to 100 (highest sensitivity); default value is 10.
timeout | The length of time, in milliseconds, of no audio before setting the Microphone.onActivity event to false; default value is 2000 (2 sec).

Microphone.setUseEchoSuppression(suppress)

Sets the echo suppression filter setting in the audio compressor.

suppress A Boolean value; a value of true turns the suppression filter on. The user can change this setting in the Flash player's Settings panel.

Microphone Properties

Microphone.activityLevel returns the amount of sound being received through the microphone source. It is great for VU meters.

Microphone.gain returns the gain value being applied to the sound source. This can be set using the Microphone.setGain() function.

Microphone.index returns the index value of the current microphone being used.

Microphone.muted returns the Boolean value if microphone access is granted by the user.

Microphone.name returns the manufacturer's name of the current sound capture device.

Microphone.names returns an array of strings containing the names of all microphone sources available to the Flash player. This will not invoke the Privacy Settings panel.

Microphone.rate returns the current sound capture frequency or sample rate in kHz.

Microphone.silenceLevel returns the value of the sensitivity setting set using Microphone.setSilenceLevel().

Microphone.silenceTimeout returns the value of time, in milliseconds, to trigger a false Microphone.onActivity event.

Microphone.useEchoSuppression returns a Boolean value indicating the status of the echo suppression filter.

Microphone Events

Microphone.onActivity is invoked when the microphone senses or stops sensing sound in the microphone range. This event can be controlled using Microphone.setSilenceLevel.

Microphone.onStatus is invoked when the status of the microphone changes. The status changes only if the user denies microphone access in the Flash player's Privacy panel. This event will receive a Microphone Information object detailed in Appendix C.


NetConnection Object

The NetConnection object maintains a two-way connection between the Flash player and the Flash Communication Server. If used on the server, it establishes a two-way connection between two Flash Communication Servers. The NetConnection object is the transport that handles streams and SharedObjects. ActionScript objects and streams are transferred between client and server or server and server using the Real-Time Messaging protocol (RTMP).

To enable Code Hints and Code Completion in the Flash MX ActionScript Editor, use the suffix _nc in the name of the NetConnection variable.

NetConnection Methods

NetConnection.call(remoteMethod, resultObject | null [, p1,…,pN])

Invokes a method defined in SSAS on the Communication Server. The method must be declared on the server within the Client object instance.

remoteMethod | The name and path (if defined) of the remote method.
resultObject | The object that handles properties returned to Flash by the server. The result object should have two methods (onStatus and onResult). Please see Appendix E,"Useful ActionScript Templates Quick Reference," to learn more about creating a resultObject handler.
p1, ... ,pN | Optional parameters required by the custom client method.

NetConnection.close()

Disconnects the client from the server, cleaning up all stream and SharedObject connections.

NetConnection.connect(targetURI, [, p1 … pN])

Requests a connection to a Flash Communication Server. This invokes the Application.onConnect handler and accepts or rejects a connection based on the custom parameters you send through the connection method.

targetURI | The Uniform Resource Identifier (URI) that references the Flash Communication Server, application, and instance. The URI must begin with RTMP:/. If no server is specified, it is assumed to be a local server and only a single forward slash is required.
p1 ... pN | Custom parameters that are handled by the application.onConnect method on the remote server.

NetConnection Properties

NetConnection.isConnected returns a Boolean value indicating an accepted or rejected connection.

NetConnection.uri returns the URI of the connection. This is a useful tool to use in the SharedObject.get() URI parameter to reference the NetConnection.

NetConnection Events

NetConnection.onStatus is invoked when the status of the NetConnection changes. The status will change with many events, most notably when the server accepts the connection. This event handles Information objects describing the level and a special event code. NetConnection Information objects are detailed in Appendix C.


NetServices Object

The NetServices object is used to transfer complex or simple ActionScript objects using Flash Remoting MX and the Action Message Format (AMF) over HTTP or HTTPS. NetServices are available for both the Flash Communication Server and the Flash player. The object can be used to call methods on an application server that is supported by Flash Remoting MX and that can return a database RecordSet or call to action other servers, such as a mail server. The server-side and client-side NetService objects are identical. On both platforms, you must manually load the RecordSet Libraries to use them.

On the server, the NetServices class is loaded automatically with the command:

load("NetServices.asc");

On the client, the NetServices class is loaded automatically with the command:

#include "NetServices.as"

NetServices Methods

NetServices.createGatewayConnection(URI)

Creates a NetServices object containing a connection to a Flash Remoting MX server. The connection is not maintained and is invoked each time a service function is invoked.

URI The Uniform Resource Identifier (URI) that references the Flash Remoting MX-enabled application server. This URI uses the HTTP or HTTPS protocol.

NetServices.setdefaultGatewayURL(URI)

Sets the default URI of the Flash Remoting MX-enabled Application Server.

URI The Uniform Resource Identifier (URI) that references the Flash Remoting MX-enabled application server. This URI uses the HTTP or HTTPS protocol.


NetStream Object

The NetStream object is a one-way streaming connection between the Flash player and the Flash Communication Server. The NetConnection is used with multiple one-way streams either from the Flash player or from the Flash Communication Server. A NetStream can handle video, audio, a combination, or broadcast messages. It can be used to send or receive live or recorded streams. The server can handle the NetStream object with its Stream object.

To enable Code Hints and Code Completion in the Flash MX ActionScript Editor, use the suffix _ns in the name of the NetStream variable.

NetStream Methods

NetStream.attachAudio(source)

Publishes an audio stream to the Flash Communication Server. This method can be used with the .attachVideo method to send synchronized audio and video on one stream.

source The Microphone object name. A value of null stops the microphone source.

NetStream.attachVideo(source | null [, snapShotMilliseconds])

Publishes a video stream to the Flash Communication Server. This method can be used with the .attachAudio method to send synchronized audio and video on one stream.

source | The Camera object name. A value of null stops the video source.
snapShotMilliseconds | The duration between "snapshots." A value of 0 snaps a picture using the camera and sends a static image as the video source. A positive value determines the time duration, in seconds, between repeated snapshots, which is useful for time-lapse photography or security applications.

NetStream.close()

Destroys the stream and all publishing or subscripting activities.

NetStream.pause(pauseResume)

Pauses toggle a subscribed playback stream.

pauseResume A boolean value; true pauses the incoming video stream and false resumes play.

NetStream.play(whatToPlay | false [,start [, length [, flushPlaylists]]])

Plays a subscribed (received) stream from the Flash Communication Server. This method starts the feed of video and audio to the targets as determined in attachVideo and attachAudio. Calling NetStream.play() also starts the client listening for broadcast (send) messages sent in the stream.

whatToPlay | The name of a live or pre-recorded stream attached to the server. Recorded stream names are accessed without the .flv extension and must exist in the streams/%instance% folder on the server. A value of false here stops the stream.
start | The start time, in seconds, to begin a pre-recorded stream. This parameter can also accept two flag values. A value of –2 first looks to play a live stream. If there is no live stream, it looks for a recorded stream. If there is no recorded and no live stream, it opens a subscription stream and waits for a client to publish to it. A value of –1 looks to play a live stream only. If no live stream is found, it opens a subscription stream and waits for a publisher.
length | The duration to play a clip, in seconds. A value of –1 plays a live stream until it is unpublished or plays the full recorded stream. A value of 0 plays a snapshot of the first frame from the start point.
FlushPlaylists | A Boolean value. True removes any previous play calls and forces the play. False adds the Play command to a local play list.

NetStream.publish(whatToPublish | false [, howToPublish])

Starts or stops publishing a stream of audio, video, and broadcast messages to the server.

WhatToPublish | The name of the published stream. This name must be unique on the server. Clients will use this name to subscribe to the stream. The server has rights to overwrite the name specified. A value of false will stop publishing.
HowToPublish | Flag values to handle stream recording; default value is live. Other values include record and append.

NetStream.receiveAudio(receive)

Toggles the audio subscription of a stream.

Receive A Boolean value; default value of true. When it is set to true, audio is received. A value of false mutes the audio.

NetStream.receiveVideo(receive | FPS)

Toggles the video subscription of a stream.

receive | A Boolean value; default value of true. When set to true, video is received. False mutes the video.
FPS | Changes the value of the frames per second received. The default is the encoded frame rate of the stream.

NetStream.seek(numberOfSeconds)

Plays the movie forward or backward relative to its current play position. This method is only available with recorded streams.

numberOfSeconds The value in seconds to play the movie forward or backward.

NetStream.send(handlerName [,p1, …,pN])

Broadcasts a message or calls a handler (function) defined on the client within the stream instance. This is a one-way broadcast and cannot handle returned objects.

handlerName The name of the function defined within the stream instance on each subscribed client.

NetStream.setBufferTime(numberOfSeconds)

The length of time or memory reserved for an incoming (subscribed) stream before it starts playing. In the case of an outgoing (published) stream, this method allocates the length of time before frames are dropped to compensate for a slower connection.

numberOfSeconds The number of seconds to be buffered before Flash stops sending data (on a publishing stream) or begins displaying data (on a subscribing stream). The default value is 0.

NetStream Properties

NetStream.bufferLength returns the number of seconds currently loaded within the stream buffer.

NetStream.bufferTime returns the number of seconds available to the buffer set by NetStream.setBufferTime.

NetStream.currentFps returns the frame rate, as a value of frames per second, on the publish or the subscription stream.

NetStream.time is the number of seconds a stream has been playing or publishing.

NetStream Events

NetStream.onStatus is invoked when the status of the NetStream changes. This event handles a NetConnection Information object described in Appendix C.Challenges to the Information object allow you to inform your user about the status of a stream or take appropriate actions in your code.


RecordSet Object

The RecordSet object can be used with or without Flash Remoting MX. The object itself is a sophisticated array of objects that operates as a standard database query result set. A series of methods and properties are available to interact with the data inside the object. This is a standard ActionScript object that can be sent to a method or occupy a slot on a SharedObject. The server-side and client-side RecordSet objects are identical. On both platforms, you must manually load the RecordSet libraries to begin using them.

On the server, the RecordSet class is loaded automatically with the command:

load("NetServices.asc");

On the client, the RecordSet class is loaded automatically with the command:

#include "NetServices.as"

To enable Code Hints and Code Completion in the Flash MX ActionScript Editor, use the suffix _rs in the name of the RecordSet variable.

Recordset Methods

RecordSet.addItem(record)

Inserts a new record into the RecordSet.

record

A Strict object containing name and value pairs with equivalent column names to the RecordSet. For example:

my_rs.addItem = ({field1:"value",field2:"value"});

RecordSet.addItemAt(index, record)

Inserts a record at a precise row number. This overwrites any data that exists at that row number. Rows start at 0.

index | The row number to add the item at.
record | The Strict object to add. See the example in addItem.

RecordSet.filter(filterFunction, context)

Creates and calls a function that you create to query the RecordSet. The results populate a new RecordSet with references to the original RecordSet.

filterFunction | A function that handles a single RecordSet record and a challenge value.
Context | A value to challenge the RecordSet.

RecordSet.getColumnNames()

Returns a string list with the names of the columns (fields) of the RecordSet.

RecordSet.getItemAt(index)

Returns a record by row (index) number. The record is returned as an object with the columns as properties. For example: my_rs.getItemAt(5).myColumn; returns the value of the column myColumn at row 5. The single parameter is:

index The index (row) of the record to be retrieved.

RecordSet.getLength()

Returns the available length, or total number of records, of the RecordSet.

RecordSet.getNumberAvailable()

Returns the total length (or total number of records) of the RecordSet. This method returns the length reported by the application server before the records have arrived, accounting for slow network connections and large RecordSets.

RecordSet.removeAll()

Deletes all records from the RecordSet leaving an empty RecordSet, for which length equals 0.

RecordSet.removeItemAt(index)

Deletes a record from the RecordSet and locks the reuse of the index number.

index The record index (row) to be permanently deleted.

RecordSet.replaceItemAt(index, record)

Replaces a complete record that exists at an index value in the RecordSet.

index | The record index (row) to be replaced.
record | A Strict object containing name and value pairs with equivalent column names to the RecordSet. Review the addItemAt method for format.

RecordSet.setDeliveryMode = function(mode, pagesize, numPrefetchPages)

Sets the way in which Flash receives RecordSets from a Flash Remoting MX server. By default, it receives the entire RecordSet when it is ready. Setting a different mode affects how records will be requested and received. Use this function with the isFullyPopulated function to ensure the integrity of the RecordSet.

[mode] | The RecordSet delivery method. The options are ondemand (default), fetchall, and page.
[pagesize] | (Optional) Used in Page mode, it identifies what the size of the page is. In Fetchall mode, it identifies how many records to fetch in each server request.
[numPrefetchPages] | (Optional) Used in Page mode, it identifies the number of pages to prefetch.

RecordSet.setField(index, fieldName, value)

Replaces the value of a single field within a RecordSet at a defined index.

index | The index of the record containing the field to replace.
fieldname | The name of the field (column) to update value.
value | The new value to set in the field.

RecordSet.sort(compareFunction)

Sorts records within a RecordSet using a custom compare function:

compareFunction A custom comparison function.

RecordSet.sortItemsBy(fieldName, direction)

Sorts records within a RecordSet by field name. This will not make a duplicate copy of the RecordSet. The sorting key is the value or data within the field.

fieldname | The name of the column (field) to sort by.
direction | Two flag values: DESC sorts the fields by descending values, and ASC sorts the fields values by ascending.

RecordSet Properties

RecordSet.isFullyPopulated() returns a Boolean value. True indicates a fully populated RecordSet.

RecordSet.isLocal() returns a Boolean value. True means the RecordSet was created locally or from an application server.

RecordSet Event

RecordSet.addView(InfoObject) is invoked when a RecordSet is changed. This method receives an Information object (or event descriptor) that contains two parameters: event and description. Refer to the list of Information objects in Appendix C for a complete list of messages that can be received. This could be used to trigger a SharedObject broadcast.


SharedObject Object

The SharedObject is a programming model that allows you to share data between communication clients or save data on a client computer in a cookie type fashion. SharedObjects on the client can be remote or local. Remote SharedObjects can be temporary or persistent. If they are temporary, they are destroyed when the last client or the server has disconnected from it. SharedObjects send synchronization messages to all connections notifying of change. These objects can be created by the server or by a client, based on the client permissions.

To use the local SharedObject:

my_so = SharedObject.getLocal("SOname");

To use the remote SharedObject:

my_so = SharedObject.getRemote("SOname");
my_so.connect(nc);

To enable Code Hints and Code Completion in the Flash MX ActionScript Editor, use the suffix _so in the name of the SharedObject variable.

SharedObject Methods

SharedObject.close()

Disconnects from a remote SharedObject.

SharedObject.connect(myRTMPConnection)

Connects the client to a remote SharedObject within the application instance identified in the Netconnection.

myRTMPConnection The name of a connected NetConnection object.

SharedObject.flush(minimumDiskSpace)

Saves a copy of the internal local SharedObject to the hard disk. The client cannot invoke a flush on a remote SharedObject.

minimumDiskSpace The value in bytes to reserve in the local SharedObject disk version. Default value is 0.

SharedObject.getLocal(objectName [, localPath])

Instantiates the local SharedObject to an internal variable and returns a reference to a locally persistent SharedObject that is available only to the current client.

objectName | The name of the local SharedObject to connect to.
localPath | The folder name of the SharedObject is stored on the client's hard disk.

SharedObject.getRemote(objectName, URI [, persistence])

Instantiates the SharedObject to a local variable and sets the SharedObject name to connect to or create. This method must be followed by a SharedObject.connect() event to connect to the remote SharedObject.

objectName | The name of the SharedObject.
URI | The URI of a communication server storing the SharedObject.
persistence | A Boolean value; true indicates that the SharedObject is persistent.

SharedObject.getSize()

Returns the size value in bytes of the local or remote SharedObject.

SharedObject.send(handlerName [,p1, …,pN])

Sends a message to all subscribed clients of the SharedObject. This call invokes a function defined by the client or server in the SharedObject Instance object.

handlerName | The name of the handler function to call.
p1, ...,pN | Any parameters required by the handler function.

SharedObject.setFps(updatesPerSecond)

Sets the listening "frequency," in frames per second, that the client will use to monitor a SharedObject for synchronization and broadcast messages.

updatesPerSecond A value, in frames per second, the client will probe the server for messages.

SharedObject Property

SharedObject.data the collection of slots or properties stored within the SharedObject. This property cannot be populated with a value; it accepts valid ActionScript variable types only.

SharedObject Events

SharedObject.onStatus handles status changes of the SharedObject. Status changes contain Information objects with code and level properties.

For a complete list of values, refer to the Appendix C,which lists all Information objects.

SharedObject.onsync is invoked on every subscriber to the SharedObject, when SharedObject properties change. The event returns an array of objects containing information on any changes to a SharedObject property.


Video Object

The Video object controls the playback of live or recorded streaming video.

To enable Code Hints and Code Completion in the Flash MX ActionScript Editor, use the suffix _video in the name of the Video variable.

Video Methods

Video.attachVideo(source | null)

Assigns a video stream to an embedded Video object that exists on the Flash stage.

source The name of a NetStream or Camera object source that is or will play a video.

Video.clear()

Clears the Video object on the Flash stage of any still images.

Video Properties

Video.deblocking = setting sets the deblocking filter on the video decompressor.

setting A Boolean value that enables/disables the automatic deblocking filter. 0 sets the deblocking filter to automatic; 1 forces never to use the filter; 2 forces to always use the filter.

Video.height returns the height value, in pixels, of the Video object.

Video.smoothing = true | false sets the smoothing filter on the video decompressor. A value of true enables the smoothing filter.

Video.width returns the width value, in pixels, of the Video object.


Appendix C. Information Objects (Server and Client) Quick Reference

Information objects are used with server-side and client-side onStatus event handlers. When the status of an object changes, the object's onStatus handler is invoked automatically. The onStatus handlers receive an Information object that usually contains at least a level and a code property. Some Information objects contain additional properties, as well.

You can use Information objects to help trap errors or inform the client when something happens. The most common onStatus Information object you will use is NetConnection.Connect.Success. When this code is received, you can use the string to control the client to start connecting SharedObjects and streams as required.

The onStatus methods must be overwritten using ActionScript or server-side ActionScript (SSAS). For example, to overwrite the onStatus event handler for the NetConnection object, you could use:

nc = new Netconnection
nc.onStatus = function(infoObj){
trace("a Status Change occurred:");
trace(" Code: " + infoObj.code);
trace(" Level: " + infoObj.level);
// Test the code property for a string value
challenge = (infoObj.code == "NetConnection.Connect.Success");
if (challenge) {
trace("The server has accepted your connection Request");
}
}

Table C.1 lists every Information object used with Communication Server elements on the server and the client. In addition to listing all the properties for each object, the table details what the information means and suggests actions you should take. The SSAS Stream object shares the NetStream Information object details.

Table C.1. Information Object Library
Code Property Level Property What This Means Other Properties
Application.Script.Error Error

Your ActionScript produced an error.

What to Do: Review the SSAS, correct the error, save and reload the application instance.

filename: The name of the script that produced the error.

lineno: The line number where the error happened.

linebuf: The source code that produced the error.
Application.Script.Warning Warning

Your ActionScript will produce an error. This is a warning message before the error occurs.

What to Do: Review the SSAS, correct the error, save and reload the application instance.

filename: The name of the script that produced the error.

lineno: The line number where the error happened.

linebuf: The source code that produced the error.
Application.Resource.LowMemory Warning

Your SSAS has consumed most of its memory resources.

What to Do: When this code is returned, SSAS should review its resources (SharedObjects, clients and streams) and start dropping things. If the application runs out of memory, it will shut down the instance.
Application.Shutdown Status

The application has shut down.

What to Do: If this is a normal operation, do nothing. If this was unexpected, you should try to reconnect.
Application.GC Status

The application instance is about to be deleted by the server.

What to Do: Nothing.
Camera.muted Status

The user did not allow the camera to be accessed by the Flash player.

What to Do: Continue the application without using the camera resource or prompt the user again to access the camera.
Camera.unmuted Status

The user allowed the Flash player to use the camera resource.

What to Do: Connect the camera feed to the stream.
Microphone.Muted Status

The user did not allow the microphone resource to be accessed by the application.

What to Do: Continue the application without using the microphone resource or prompt the user again to access the microphone.
Microphone.Unmuted Status

The user allowed the application to use the microphone resource.

What to Do: Connect the microphone feed to the stream.
NetConnection.Call.Failed Error

The server-side method (function) produced an error or was not available.

What to Do: Check that the method exists. Check that you have the correct case (server methods are case sensitive). Check that you have passed the proper parameters.

Description: Details why the method call failed, which is useful for debugging.
NetConnection.Connect.AppShutdown Error

If the administrator has shut down the server, rebooted, or reloaded the application, the client will use the AppShutDown event responder to handle the error. This error will also be received if there is an unexpected shutdown of the server. You can use this to display a message to the user that the connection has been lost or you can enter the client in a reconnect loop.

What to Do: Check the server for a crashing sequence. Try reconnecting to re-establish the application and instance. Reload the application in the App Inspector.
NetConnection.Connect.Closed Status

When a NetConnection.close()command is issued to the server, the server will handle it using the Application.onDisconnect event. This event will change the status of the connection and will report it to the client, where the onStatus event will handle the response.

What to Do: Nothing, this is not an error state.
NetConnection.Connect.Failed Error

This error will be returned if the server was not found on the network.

What to Do: Ensure the server is running. Ensure you are connecting to the server with the proper URI (IP address or domain). Ensure you have the correct port. Check any firewalls to ensure the ports are open. Check your network connection.
NetConnection.Connect.InvalidApp Error

The server was found, but the application you referenced was not.

What to Do: Check that the application folder exists within the server's application directory. Check that you have spelled the application name correctly. If you are using NetConnection in SSAS, remember to check case sensitivity.
NetConnection.Connect.Rejected Error

This error is returned by the server function, Application.rejectConnection().

What to Do: Check the values of the parameters sent from the client challenged by the server. An easy way to check these is to use a server-side trace and watch the App Inspector.

Application: Contains application information for why the connection was rejected.
NetConnection.Connect.Success Status

You have successfully connected to the server.

What to Do: Go get a coffee and comb your hair, because someone may be watching you!
NetStream.Buffer.Empty Status

This code is sent when there is network congestion or the stream is too big for the bandwidth. It gets triggered when the buffer contains no data during a NetStream. It may be a temporary state. When data has filled the buffer again, the NetStream.Buffer.Full status will be sent.

What to Do: Check the network connection and bandwidth between server and client. Possibly re-encode the video file, if you are streaming pre-recorded video. You should send a warning to the user, letting them know your stream is buffering.
NetStream.Buffer.Full Status

When the stream has been filled after being empty, this status is sent. Video will start playing again.

What to Do: Watch the video.
NetStream.Failed Error

This error will be sent if there is a problem with a NetStream command. This has been known to happen often when using the seek method.

What to Do: This error will happen when you quality check your application. Check that you are sending all the parameters required by the method you are calling.

Description: Contains a detailed reason why the stream failed.
NetStream.Pause.Notify Status

This is a useful status to acknowledge the client's pause request.

What to Do: Nothing.
NetStream.Play.Failed Error

This is a general catch-all message. If the error could not be reflected by any other message in the Information object, this code will be returned.

What to Do: check the stream name you are trying to connect to. Also, the client instance may not have sufficient read permissions set on the server by Client.readAccess.

Description: Contains a detailed reason why the Stream.play method failed.
NetStream.Play.PublishNotify Status

This is a useful message that informs all subscribers a publish stream has started.

What to Do: Possibly begin playing the subscribed stream.
NetStream.Play.Reset Status

This status will be returned when the play list has been flushed.

What to Do: Use this as a notification message to start the play sequence again.
NetStream.Play.Start Status

The stream has started to play.

What to Do: Watch the video.

Details: The name of the current stream that is playing.
NetStream.Play.Stop Status

The stream has been stopped.

What to Do: If this is a normal operation, then do nothing. If this is unexpected, then check the connection and try to reconnect. If it is a subscribed stream, the stream may have been terminated by the source or the server.
NetStream.Play.StreamNotFound Error

The stream requested was not found. This could be either a live stream or a recorded stream.

What to Do: Check the spelling of the stream reference. If playing a recorded stream, ensure the file exists in the proper folder.
NetStream.Play.UnpublishNotify Status

Every client who is subscribed to the stream will be sent this status update when the publisher has stopped sending the stream.

What to Do: You should listen for this, and handle it with a close() function.
NetStream.Publish.BadName Error

This error is sent to the client trying to publish a stream using a name that is already in use.

What to Do: An easy way to ensure this will not happen is to check the username upon connection and to name your streams relative to the username. You can also use this in combination with a timestamp on the stream, as in Kevin_1853.flv.
NetStream.Publish.Idle Status

The publisher of the subscribed stream has kept a nonactive stream open too long.

What to Do: You should close the stream to free up resources.
NetStream.Publish.Start Status

Your stream has started to publish.

What to Do: The stream has successfully started publishing to the server.
NetStream.Record.Failed Error

This error code will be returned when the stream is no longer to be recorded. Most times, this is a result of a disk becoming too full. This is also used as a catch-all error message.

What to Do: Check your hard drive for space. If you are running a quota system, ensure the streams folder has enough space.

Description: Contains a detailed reason why the stream.record method failed.
NetStream.Record.NoAccess Error

If a client tries to record a stream that still has a subscription to it, this code will be returned. The code will also notify if the folder or file is set to read only.

What to Do: Check the Client.writeAccess on the server. Check the free space on the server's hard disk.
NetStream.Record.Start Status

A client has started to publish a stream being recorded on the server.

What to Do: You could use this code to trigger a record light. This is important because there may be a delay in the record start.
NetStream.Record.Stop Status

Recording has stopped.

What to Do: Use this to notify the user that recording has finished.
NetStream.Seek.Failed Error

When using a seek command, this error will be returned if you try to seek to a time within the movie that doesn't exist, such as –1.

What to Do: Check the formula for your seek command. Place checks in to ensure you don't over seek or under seek.
NetStream.Seek.Notify Status

A successful seek command will return this status code.

What to Do: Start playing from the seek value.
NetStream.Unpause.Notify Status

Playback has started from the point of pause.

What to Do: Watch the video.
NetStream.Unpublish.Success Status

This code will be returned when a successful Close()has been sent when publishing.

What to Do: Nothing.
SharedObject.BadPersistence Error

This error will occur when you subscribe to a SharedObject and pass the wrong persistence value in the .get method.

What to Do: Change the persistence value to connect.
SharedObject.Flush.Failed Error

This error will occur on the client, usually with a local SharedObject. If the command referenced an amount of disk space that is unavailable, this error will be shown.

What to Do: Lower the amount of disk space required or prompt the user to increase the amount of disk space for local SharedObjects.
SharedObject.Flush.Success Status

The persistent SharedObject has been saved to hard disk successfully.

What to Do: Nothing.
SharedObject.UriMismatch Error

The URI (or application instance) passed by the client in the .get method does not match the (URI) of the SharedObject.

What to Do: Use the URI(nc) function to correctly access the remote SharedObject.


Appendix D. Macromedia Flash UI Component Objects Quick Reference

The Flash UI components offer fast solutions to create full-featured communication applications. The components each have a programming interface to control them using ActionScript. All components can operate with minimal ActionScript using the SimpleConnect UI component. This Appendix provides quick descriptions of the components, as well as their ActionScript methods and properties.

When naming instances of the Communication UI components, use the MovieClip suffix (_mc). These components will respond to the methods and properties defined within the MovieClip object.

Figure D.1. The Flash UI Components panel in Flash MX
    [ Team LiB ]


Common Methods

Most Flash UI component classes share some common methods among them. These three methods are available in every component class unless noted in the component description.

[component]_mc.connect(nc)

This method initializes the object. The internal initialization process is different for each object, but they will all use this method to attach to a NetConnection and call the function .setUsername() with the name used in the connection process. This method also initializes the server-side ActionScript handlers. The value of nc is the instance name of the active NetConnection object.

[component]_mc.setUsername(newName)

This method assigns the username to the component. In the case of the PeopleList component, this is the name that appears in the list of users. The value of newName is the name of the user that is connected to the component. If you do not include the parameter, the user is in Lurker mode.

[component]_mc.close()

This method disconnects the component from the connection. It will release all resources being used on the server and on the client.


Lurker Mode

Many of the Communication UI components also support Lurker mode. This mode is simply a connection where the username is null (not defined). The user will be able to "watch" the activity on supported components, such as Chat, but will not have the ability to interact, such as post a message. To place a user into Lurker mode using ActionScript, use the setUserName() method to set the username to null. If you are using the SimpleConnect component, then prompt your user to remove their name and press Login.


Macromedia Flash UI Component ActionScript Objects

This section presents the unique ActionScript Methods and properties used by the Communication UI components.

FCAudioConference Object

The AudioConference component provides two-way (full-duplex) audio communication between all clients connected to the application instance. There are no ActionScript methods other than the common methods mentioned above.

FCAVPresence Object

The AVPresence component enables a camera and microphone on the client. Each component can receive and send an audio/video stream to the application instance. Remember to set the Presenter SharedObject property to a unique value in the properties panel. There are no ActionScript methods other than the common methods mentioned above.

FCChat Object

The Chat component provides a live chat window among all communication clients. The component offers a history window and a text input area. This component supports Lurker mode. The component has methods and roperties within the server-side ActionScript object, FCChat.

chat_mc.clearHistory()

This method will delete all chat history from the history window. If the server-side property FCChat.prototype.allowClear is false, this method will not run.

FCChat Server-Side Object

The server-side counterpart to the Chat UI component object controls the operation of the chat history. These settings must be set in the application.onAppStart function. Setting them in application.onConnect will reset the prototype each time a user connects.

FCChat.prototype.clearHistory()

This SSAS method clears all chat history and forces each client to update. It is not subject to the allowClear property.

FCChat.prototype.histlen=maxHistory

This property sets the maximum number of text messages stored on the server. The default value is 250.

FCChat.prototype.persist=true

This property sets the chat history to persist even when the application is reloaded. The default value is true.

FCChat.prototype.allowClear=true

This read/write property defines whether a chat history can be cleared from the client. The values true and false are Boolean values that determine whether the user can clear the history. The default value is true.

FCConnectionLight Object

The ConnectionLight component visually shows a NetConnection status. It is also a button that, when clicked, displays information about the connection. The button has four color states:

Green | Server connection is established.
Yellow | Network congestion (high latency).
Red | Server disconnected.
Gray | Component is not assigned.

The setUserName method is not used with this object.

connectLight_mc.measurementInterval=intervalValue

This property sets the sample rate of bandwidth and latency.

connectLight_mc.latencyThreshold=latencyTValue

This property controls the latency value that will turn the light yellow.

FCCursor Object

The Cursor component is an avatar that represents the mouse pointer of every communication client. The username of the client is shown below the pointer. The client can choose the color of the pointer using the UserColor component.

cursor_mc.setColor(newColor)

This method changes the color of the pointer across all clients. The value of newColor is a hexadecimal color value, such as 0xFC00F3.

FCPeopleList Object

The PeopleList component displays all users connected to the application instance. Lurkers are not displayed here.

peopleList_mc.lurkers

This property returns the number of connected clients that have not supplied a username (in Lurker mode). The value is an integer.

peopleList_mc.users

This property returns the number of connected clients that have supplied a username. The value is an integer.

FCPresentationSWF Object

The PresentationSWF component provides a framework to use a special slideshow SWF movie that is dynamically loaded from a web server on each client. The component has two modes: Presenter and Viewer.

The setUserName method is not used with this object.

presentSWF_mc.loadSWF(swfFile)

This method can be called by the "presenter" application. It dynamically loads a new Flash SWF movie on all subscribed clients. swfFile is the absolute or relative location to load a SWF movie

presentSWF_mc.next()

This method moves the play head of the slideshow movie one frame forward. If used within the presenter application, all clients are affected. If used within the viewer application, only the local frame is affected.

presentSWF_mc.back()

This method moves the play head of the slideshow movie one frame backward. If used within the presenter application, all clients are affected. If used within the viewer application, only the local frame is affected.

presentSWF_mc.sync()

This method moves the play head of the slideshow movie to the same frame as the presenter. It can be used in the viewer application only.

_global.speakerMode=true

This _global variable is monitored by the component to control what state the Flash movie is in. A value of true enables Speaker (or Presentation) mode.

FCPresentationText Object

The PresentationText component provides a stage to collaboratively produce and deliver a presentation. It operates in two modes: Presenter and Viewer (the default).

presentText_mc.nextSlide()

This method moves the presentation one frame forward. If used within the presenter application, all clients are affected. If used within the viewer application, only the local frame is affected.

presentText_mc.backSlide()

This method moves the presentation one frame backward. If used within the presenter application, all clients are affected. If used within the viewer application, only the local frame is affected.

presentText_mc.newSlide()

This method creates a new slide in the presentation. It is only available in Presenter mode.

presentText_mc.deleteSlide()

This method removes a new slide in the presentation. It is only available in Presenter mode.

FCRoomList Object

The RoomList component provides a management framework for developing Lobby applications. The component requires advanced development of HTML files, JavaScript, and Flash Communication Applications. It offers functions for users to create, delete, and join "room" applications, such as a chat room.

roomList_mc.createRoom()

This method calls the Create Room dialog box. The user is required to enter a new room name to create.

roomList_mc.deleteRoom()

This method removes a room from the Room list.

FCSetBandwidth Object

The SetBandwidth component provides a simple drop-down box to let the client control inbound and outbound bandwidth between the server. There are four options: Modem, DSL, LAN, and custom. This component is useful if you expect a diverse range of connections to use your application.

The setUserName method is not used with this object.

The properties of SetBandwith let you set the upload and download bandwidth manually. Each property has a default integer value that represents a speed in kilobits per second (Kbps).

setBand_mc.modemUp=maxSpeed

This property sets the upload bandwidth for Modem. The default value is 33Kbps.

setBand_mc.modemDown=maxSpeed

This property sets the download bandwidth for Modem. The default value is 33Kbps.

setBand_mc.dslUp=maxSpeed

This property sets the upload bandwidth for DSL. The default value is 128Kbps.

setBand_mc.dslDown=maxSpeed

This property sets the download bandwidth for DSL. The default value is 33Kbps.

setBand_mc.lanUp=maxSpeed

This property sets the upload bandwidth for LAN. The default value is 1000Kbps (1Mbps).

setBand_mc.lanDown=maxSpeed

This property sets the download bandwidth for LAN. The default value is 1000Kbps (1Mbps).

FCSimpleConnect Object

The SimpleConnect component establishes a connection and a user between the Flash player and the server. It can be used with all Flash UI components. Using this component requires no (or very little) ActionScript on the client or the server. This object has no methods and no ActionScript methods or properties.

FCUserColor Object

The UserColor component allows a client to select a color that will identify him. This component can be used with the Chat and the Cursor components. It also sets a global color value that can be used with future Communication components. The setUserName method is not used with this object.

FCVideoConference Object

The VideoConference component reuses the AVPresence component to provide a quick solution for video conferencing. There are no ActionScript methods other then the common methods mentioned previously.

FCWhiteBoard Object

The WhiteBoard component provides a shared drawing space that lets you collaborate with annotations. This can be used as a straight white board or overlaid on an image. The component supports limited drawing tools including text, shape, and line drawing. There are no ActionScript methods other then the common methods mentioned previously. The setUserName method, however, is not used with this object.


Appendix E. Useful ActionScript Templates Quick Reference

This quick reference is a collection of scripts between Macromedia Flash, Flash Communication Server, and Flash Remoting MX. They are provided here as a foundation for you to build on. They will help you quickly build Flash Communication Server applications using ActionScript. The ActionScript for this appendix can be downloaded from the book's web site (http://flashcom.PangaeaNewMedia.ca/).


Checklist for Creating a New Application

When you create a new application, follow this simple checklist:

  1. Create an Application folder within the flashcom/applications folder on the Flash Communication Server.

  2. Create a main.asc file in the root of your new application folder.

  3. Add the following code to the main.asc file only if you are using the Flash UI components:

    load("components.asc");

  4. Add the following code to the main.asc file only if you are using the Flash Remoting MX or the RecordSet object:

    load("NetServices.asc");

  5. If you are streaming video, create a folder called streams in your application folder.

  6. Copy any Flash video assets (FLV files) to a folder using the same name as the application instance. (If you do not specify an application instance, place your video in the default instance, which is _definst.)

  7. Create a new Flash movie within Flash MX.

  8. Save the movie in a folder accessible by the web server or accessible by multiple computers.

These steps will help you quickly get started with your Flash Communication Server applications. The next series of samples will help you with specific tasks. Remember, each code sample is available on the book's web site (http://flashCom.PangaeaNewmedia.ca/ ).


ActionScript Connect and Connect UI Components

When you do not plan to use the SimpleConnect UI component, use these scripts in Listings E.1 and E.2 on the client and on the server to make your connection work with other UI components.

Listing E.1 Flash ActionScript
// instantiate the NetConnection Object
nc = new NetConnection();
// create an onStatus Handler for nc
nc.onStatus = function(info) {
      trace("LEVEL: "+info.level+"  CODE: "+info.code);
      if (info.code == "NetConnection.Connect.Success") {
            // ** place your code here to execute when the server accepts **
      }
};

// make a connection request (invoke the application.onConnect)
// pass two additional parameters to the onConnect method (userName, Password)
nc.connect("rtmp://myApplication/myInstance", "Tracey Davis", "Bert");

// Connect any UI Components to the connection
peopleList_mc.connect(nc);
connectionLight_mc.connect(nc);
chat_mc.connect(mc);
Listing E.2 Server-Side ActionScript (main.asc)
// Load the Flash UI component server-side objects
load("components.asc");

// Listen for the new connection to this application.
// userName is a parameter passed in from the client-side nc.connect call.

application.onConnect =function(newClient,userName,password)
{
      // Set the global user name for the UI Components
      // with the user name passed into this function.
      gFrameworkFC.getClientGlobals(newClient).username =newUserName;

      // Accept the connection from the user,
      // This line will invoke the NetConnection onStatus handler
      application.acceptConnection(newClient);

      // Trace Output that will appear in the App Inspector
      trace("hello There," + userName);
      trace("A Flash Client was just connected");
}


Publish a Camera and Microphone

Listing E.3 publishes your camera and microphone to a NetConnection. The connection script uses the UI components technique from Listings E.1 and E.2.

Listing E.3 Flash ActionScript for Publishing a Camera and Microphone
nc = new NetConnection();
nc.onStatus = function(info) {
      trace("LEVEL: "+info.level+"  CODE: "+info.code);
      if (info.code == "NetConnection.Connect.Success") {
            // Call a function to setup the NetStream Publish when the server accepts the
  connection
            startStreamPublish();
      }
};
startStreamPublish = function () {
      // attach the Camera feed to an Embedded Video Object named, "my_video"
      // that exists on the Flash Stage.
      my_video.attachVideo(Camera.get());
      // attach a NetStream to the variable, publish_ns
      publish_ns = new NetStream(nc);
      // attach the Microphone and Camera to the publish_ns stream
      publish_ns.attachAudio(Microphone.get());
      publish_ns.attachVideo(Camera.get());
      // start publishing the combined camera and microphone feed
      publish_ns.publish("myStream");
};

nc.connect("rtmp://myApplication/myInstance", "Tracey Legault-Davis", "Bert");

The SSAS ActionScript template in Listing E.2 can be used with this ActionScript.


Subscribe to a Live or Recorded Stream

The script in Listing E.4 subscribes to, or receives, a live or prerecorded video (FLV) stream that is available within the application instance's streams folder.

Listing E.4 Flash ActionScript for Subscribing to or Receiving a Video Stream
nc = new NetConnection();
nc.onStatus = function(info) {
      trace("LEVEL: "+info.level+"  CODE: "+info.code);
      if (info.code == "NetConnection.Connect.Success") {
            // Call a function to setup the NetStream Subscription
            startStreamSubscribe();
      }
};
startStreamSubscribe = function () {
      // that exists on the Flash Stage.
      // attach a NetStream to the variable, sub_ns
      sub_ns = new NetStream(nc);
      // attach the Subscription source to a Video Object on the stage
      my_video.attachVideo(sub_ns);
      // Start the stream, "serverStream", (-2) if the live source is not available,
      // look for a recored stream of the same name.  (-1)Play until the stream is over
      sub_ns.play("serverStream", -2, -1);
};
nc.connect("rtmp://localhost/myApplication/myInstance", "Tracey Davis", "Bert");

The SSAS ActionScript template in Listing E.2 can be used with this ActionScript.


onStatus Catch-All Template (SSAS and Flash)

Use this script to overwrite all onStatus function prototypes. By including this script template, you will not be required to define any onStatus events. This is an excellent tool for debugging.

Listing E.5 onStatus (Catch-All) ActionScript Template
function onStatusTemplate(info) {
      infoMessage_array = info.code.split(".");
      trace(" ** Status Message Received for: "+infoMessage_array[0]+" **");
      trace(" ** "+new Date());
      trace("    |::: Level—> "+info.level);
      trace("    |::: Code —> "+info.code);
      // Trace extra Information properties
      if (info.description != undefined) {
            trace("    |::: Description—> "+info.description);
      }
      if (info.details != undefined) {
            trace("    |::: Details—> "+info.details);
      }
      if (info.application != undefined) {
            trace("    |::: Application—> "+info.application);
      }
      switch (infoMessage_array[0]) {
      case "Application" :
            trace("    | ::::Application Messages");
            // Display Script Error Messages
            if (infoMessage_array[1] == "script") {
                  trace("    |::: Script Error Details.  Filename—> "+info.filename+"
  Line—> "+info.lineno);
                  trace(info.linebuf);
            }
            // Place Code Here
            break;
      case "Camera" :
            //   | :::: Handle Camera Messages
            // Place Code Here
            break;
      case "Microphone" :
            //    | :::: Handle Microphone Messages
            // Place Code Here
            break;
      case "NetConnection" :
            //    | ::: Handle NetConnection Messages
            if (infoMessage_array[2] == "Success") {
                  trace("    |::* Connection was Accepted by the Server , continuing to
  load!");
                  // Scripts to run when the Connection has succeeded
                  nc.call("sayHelloServer", new server_ret());
                  nc.call("setConnectTimes", new server_ret());
                  connectObjects();
                  streamIt();
            }
            // Place Code Here
            break;
      case "NetStream" :
            //    | :::: Handle NetStream Messages
            // Place Code Here
      }
      trace(" ** End Status Message for: "+infoMessage_array[0]+" **");
      trace("");
}

Listings E.6 and E.7 will assign this template to the object onStatus prototypes on the Client and in SSAS.

Use the ActionScript in Listing E.6 in Flash to use the onStatus template in Listing E.5 to overwrite the object prototypes. Trace actions will appear in the Flash Output window, when testing your Flash movie in Flash MX.

Listing E.6 Overwrite Flash ActionScript Object's onStatus Event
// Client Side Objects
Camera.prototype.onStatus = onStatusTemplate;
Microphone.prototype.onStatus = onStatusTemplate;
NetConnection.prototype.onStatus = onStatusTemplate;
NetStream.prototype.onStatus = onStatusTemplate;
SharedObject.prototype.onStatus = onStatusTemplate;

Use the ActionScript in Listing E.7 in SSAS to use the onStatus template in Listing E.5 to overwrite the object prototypes. Remember, the ActionScript in Listing E.5 must be added or loaded into the main.asc file for this to work. Trace actions will appear in the App Inspector or the NetConnection Debugger.

Listing E.7 Overwrite Server-Side ActionScript Object's onStatus Event
/* main.asc file */
// Server Side Objects
Application.prototype.onStatus = onStatusTemplate;
Stream.prototype.onStatus = onStatusTemplate;
SharedObject.prototype.onStatus = onStatusTemplate;


onSync Template (SSAS and Flash)

The script template in Listing E.8 can be used to handle any SharedObject onSync event on the client and the server.

Listing E.8 onSync ActionScript Template
onSyncTemplate = function (info) {
      trace("Synchronizing Data");
      //
      // Use this structure as a prototype for your onSync Handlers.
      // Loop through the Array of Objects using the IN operator
      //
      for (name in info) {
            trace("[sync] Reading Array Object #"+name+" code("+info[name].code+",
  "+info[name].name+")");
            //
            // ::: The following switch handles code values returned by the object
            // Place Code Here
            //
            switch (info[name].code) {
            case "change" :
                  trace("::Handle a change of data by another client");
                  // Place Code Here
                  break;
            case "success" :
                  trace("::Handle successful change of data from this server");
                  // Place Code Here
                  break;
            case "reject" :
                  trace("::Handle a rejected SharedObject write operation");
                  // Place Code Here
                  break;
            case "clear" :
                  trace("::Handle an initialization of the SharedObject");
                  // Place Code Here
                  break;
            case "delete" :
                  trace("::Handle deleted Attributes");
                  // Place Code Here
             }
            // ::: End the Switch, continue Looping through the Information Object
      }
      // ::: Complete the onSync Handler
};

// Connect to Remote SharedObject using the onSync Template
rem_so = SharedObject.getRemote("myRemoteSO", nc.uri, true);
rem_so.onSync = onSyncTemplate;
rem_so.connect(nc);


Connect and Create a Remote SharedObject (Flash)

Listing E.9 will connect the Flash client to a persistent remote SharedObject. If the object does not exist, it will be created. There is a simple read and write sample included.

Listing E.9 Flash ActionScript for Creating a Remote SharedObject
initRemoteSharedObject = function () {
      trace("Connect a Remote SharedObject");
      rem_so = SharedObject.getRemote("myRemoteSO", nc.uri, true);

      // Note: the following onSync event uses the onSync template script
      rem_so.onSync = onSyncTemplate;
      rem_so.connect(nc);

      // Write properties (slots) to the Remote SharedObject
      rem_so.data.simpleTest = "FlashCom will change the world!";
      rem_so.data.arrayTest = ["Brett", "Mike", "Ryan", "Paul", "Jody", "Kevin"];

      // Read properties (slots) from a Remote SharedObject
      var my_var = rem_so.data.test;
      var my_array = rem_so.data.arrayTest;
      trace(" Remote SharedObject Read Test: "+my_var);
      trace(" Remote SharedObject Read Test: "+my_array[0]);
      trace("Remote SO Size: "+rem_so.getSize());
};


Connect and Create a Local SharedObject (Flash)

Listing E.10 will connect the Flash client to a persistent local SharedObject on the client's hard disk. If the object does not exist, it will be created. There is a simple read and write sample included.

Listing E.10 Flash ActionScript for Creating a Local SharedObject
initLocalSharedObject = function () {
      trace("Connect a Local SharedObject");
      lcl_so.getLocal("myLocalSharedObject");
      // Write a property to the Local SharedObject
      lcl_so.test = " kevin";
      // Read a property from a Local SharedObject
      var my_var = lcl_so.test;
      trace(" Local SharedObject Read Test: "+my_var);
      trace("LocalSize: "+lcl_so.getSize());
};


Connect and Create a SharedObject (SSAS)

The script in Listing E.11 will connect the Flash Communication Server client to a persistent SharedObject. If the object does not exist, it will be created. There is a simple read and write sample included.

Listing E.11 Server-Side ActionScript (main.asc) for Creating a SharedObject
application.onAppStart = function() {
      initSharedObject();
      }

initSharedObject = function () {
      // Create a new or connect to an existing persistent SharedObject
      server_so = SharedObject.get("mySharedObject", true);
      // Note: the following onSync event uses the onSync template script
      server_so.onSync = onSyncTemplate;
      // Write a property to the SharedObject using the setProperty method
      server_so.setProperty("myProperty", "myValue");
      // Read a property from the SharedObject using the getProperty method
      var my_var = server_so.getProperty("getWhatsNew_rs");
      trace("SharedObject Read Test: "+my_var);
};


Connect a Database with Macromedia Flash Remoting MX Using SSAS

The server-side ActionScript (SSAS) in Listing E.12 connects to a Flash Remoting MX service to perform a simple user login authentication. The service is defined when the application starts. A Service method is called and handled when the client connects. Remember, Flash Remoting MX is nonpersistent. A connection is established each time a service method is invoked.

Listing E.12 Server-Side ActionScript for Connecting a Database with Flash Remoting MX
// Load the NetServices Class Libraries
load("netservices.asc");
// When the application Starts, setup the non-persistent Flash Remoting server
application.onAppStart = function() {
      trace("Application was loaded, Cap'n");
      NetServices.setDefaultGatewayUrl("http://localhost/flashservices/gateway");
      var gatewayConnection = NetServices.createGatewayConnection();
      //  instantiate the service into a local variable
      var cf_service = gatewayConnection.getService ("myFlashComService.login_service",
  this);
};

application.onConnect = function(clientObject, username, password) {
      // call the server function, authenticateUser, passing the username and password
      var callTheServer = cf_service.authenticateUser(username, password);
      // handle the server response
      this.authenticateUser_Result = function(result_rs) {
            trace("The Server Responded  —> "+ result_rs.getLength());
            trace("The firstName value of row 0  —> "+ result_rs.items[0].firstName);
            };
      // handle any server errors
      this.authenticateUser_Status = function(status) {
            trace("Returned FAILED From the Server");
      };
};


Connect a Database with Macromedia Flash Remoting MX Using Flash ActionScript

The Flash ActionScript in Listing E.13 connects the Flash player directly to a Flash Remoting MX service. A Service method is called and handled similar to the SSAS operation. Remember, Flash Remoting MX is nonpersistent. A connection is established each time a service method is invoked.

Listing E.13 Flash ActionScript for Connecting a Database with Flash Remoting MX
// Include the Required Flash Remoting NetService class files
#include "NetServices.as"
#include "NetDebug.as"

// Define the connection to the Flash Remoting Server
NetServices.setDefaultGatewayUrl("http://localhost/flashservices/gateway");
gatewayConnnection = NetServices.createGatewayConnection();

// Define the service to a local variable, cf_service
cf_Service = gatewayConnnection.getService("myFlashComService.login_service", this);
trace("REMOTING INITIALIZED");

// Call a Remoting Service Function
cf_service.authenticateUser("Kevin", "TIN");

// Handle the Service method, "authenticateUser" when returned from the server
authenticateUser_Result = function (result_rs) {
      trace("The Server Responded  —> "+result_rs.getLength());
      trace("The firstName value of row 0  —> "+result_rs.items[0].firstName);
};

// handle any server errors
authenticateUser_Status = function (status) {
      trace("Returned FAILED From the Server");
};


Invoking a Server Function from Macromedia Flash

Listing E.14 will call the method sayHelloServer, which was created in the SSAS Client object when the client connected.

Listing E.14 Flash ActionScript for Invoking a Server Function
nc = new NetConnection();
nc.onStatus = function() {
     nc.call("sayHelloServer", new server_ret());
};
nc.connect("rtmp://localhost/myApplication/myInstance");

// handle the method results returned from the server.
server_ret = function () {
      this.onResult = function(value_ret) {
            trace("Message From the Server: "+value_ret);
      };

      this.onStatus = function() {
            trace("Method Failed");
      };

};

There are two ways to create a client function on the server. Option A (in Listing E.15) creates the function on the unique client instance when it connects.

Listing E.15 Server-Side ActionScript (Option A) for Invoking a Server Function
application.onConnect = function(clientObject) {
      application.acceptConnection(clientObject);

      // Define a function for the Client to Call  - send him an object
      clientObject.sayHelloServer = function() {
            // Trace in the App Inspector
            trace("The client says How Ya Doin, Bucko.. Got Somthin' for ya!");

            // return a string to the Flash Player
            return ("FlashCom Server Rocks!");
      };
};

Shown in Listing E.16, Option B will create a prototype function that all clients can access.

Listing E.16 Server-Side ActionScript (Option B) for Invoking a Server Function
clientObject.prototype.sayHelloServer = function() {
      // Trace in the App Inspector
      trace("The client says How Ya Doin, Bucko.. Got Somthin' for ya!");
      // return a string to the Flash Player
      return ("FlashCom Server Rocks!");
};


Invoking a Macromedia Flash Function from SSAS

These scripts will define a function on the Flash client and call it from the server. Functions are defined as methods in the NetConnection object on the client. They are called from the Client object in SSAS.

The ActionScript in Listing E.17 defines a function in Flash called sayHelloClient. It will be called by SSAS in Listing E.18.

Listing E.17 Flash ActionScript for Defining a Flash Function
nc = new NetConnection();
nc.connect("rtmp://localhost/myApplication/myInstance");

// Define the Function that the server will call in the NetConnection
nc.sayHelloClient = function() {
      trace("The Server says.. Yo, Dude!");
};

The ActionScript in Listing E.18 calls the client function set in Listing E.17.

Listing E.18 Server-Side ActionScript (main.asc) for Calling the Client Function
application.onConnect = function(clientObject) {
      application.acceptConnection(clientObject);

      // invoke the function on the Client
      clientObject.call("sayHelloClient");
};


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

.call()
NetConnection methods
.clear method
.close()
NetConnection methods
SharedObjects methods
.connect method
.connect()
NetConnection methods
SharedObjects methods
.data
SharedObjects properties
.flush
.flush()
SharedObjects methods
.getSize()
SharedObjects methods
.IsConnected
NetConnection properties
.onSync method
synchronization
.purge
.send method
.send()
SharedObjects methods
.send() function
.setFPS()
SharedObjects methods
.uri
NetConnection properties
/ (forward slash)
_pso suffixes

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

absolute URIs
acceptConnection()
access
to adaptors and virtual hosts
giving to users
access security 2nd
accessing
ActionScript Editor
Action Message Format (AMF)
Action Message Format. [See AMF]
Actions panel
ActionScript Editor
ActionScript 2nd
client-side ActionScript. [See client-side ActionScript]
code for Living Emoticon 2nd 3rd 4th 5th 6th 7th 8th 9th 10th
code hints
suffixes 2nd
coding strategies
client/server roles 2nd
data storage 2nd 3rd
timelines 2nd
connecting UI components 2nd 3rd 4th 5th 6th 7th 8th 9th 10th 11th
controller applications 2nd 3rd
leaf1_mc[property] 2nd
main.asc
server-side
in Lobby applications 2nd
server-side ActionScript 2nd 3rd 4th
style and formatting 2nd
avoiding spaghetti code
commenting 2nd
naming variables
placing code
using functions
subscriber applications 2nd 3rd
ActionScript Editor
accessing
Actions panel
ActionScript panel
code hints
communications book
Expert mode 2nd
Normal mode
ActionScript interpreter 2nd 3rd 4th 5th
ActionScript panel
ActionScript Editor
Communication object library
ActionScript. [See also code]
Adaptor node
Adaptor.xml
adaptors 2nd 3rd
adaptor folder
architecture of Flash Communication Server
Adaptor.xml
folders
security
creating 2nd 3rd 4th 5th 6th 7th
giving users access
registering
adding
class files
NetDebug class files 2nd
IP addresses in Windows
server users
virtual host users
Admin port
Administration Console 2nd 3rd 4th 5th
accessing from within Flash
Administration Users panel 2nd 3rd
Diagnostic panel 2nd
License panel
Live Log panel
logging into 2nd 3rd 4th
Maintenance panel
applications
servers
virtual hosts
screens
Administration Users panel
Administration Console 2nd 3rd
administrators
virtual hosts
Allow node
AMF (Action Message Format) 2nd
API (application programming interface)
APIs (application programming interfaces)
App Inspector 2nd 3rd 4th
Application Instances panel 2nd
Live Log panel 2nd
loading applications 2nd 3rd 4th
Statistics Monitor panel 2nd 3rd
verifying code
Apple QuickTime
Application folder
Application Inspector
accessing from within Flash
Application Inspector Console
application instances 2nd 3rd
calling from SSAS 2nd 3rd 4th 5th
creating 2nd 3rd
Application Instances panel
App Inspector 2nd
Application objects
SSAS 2nd
application programming interface. [See API]
application programming interfaces. [See APIs]
application server
Application Servers
Remoting 2nd
Application.xml 2nd
ApplicationGC
applications
architecture of Flash Communication Server
Application.xml 2nd
folders
security
controller applications 2nd
user case studies
defining on the server 2nd 3rd
files used
initializing
Live Support Lobby 2nd 3rd
instances
SSAS 2nd
Live Support Session. [See Live Support Session]
loading
with App Inspector 2nd 3rd 4th
Lobby 2nd
call to Lobby
call to Room
coding 2nd
developing 2nd 3rd
initialization 2nd 3rd 4th 5th 6th 7th
RoomList UI component 2nd 3rd 4th
server-side ActionScript 2nd
Maintenance panel
Administration Console
representative
Live Support Session 2nd 3rd 4th 5th 6th
subscriber applications
user case studies
technical support applications. [See technical support applications]
testing
text messaging
testing
text messaging, adding
colors, selecting 2nd 3rd
troubleshooting 2nd 3rd
video, adding 2nd
setting bandwidth 2nd 3rd
streams
testing 2nd 3rd 4th 5th
troubleshooting
Virtual Classroom. [See Virtual Classrooms]
appLogin
appLogin method
architecture of Flash Communication Server 2nd 3rd
adaptors
Adaptor.xml
folders
security
applications
Application.xml 2nd
folders
security
servers 2nd 3rd 4th
security 2nd
Server.xml 2nd 3rd 4th
users 2nd
virtual hosts
folders 2nd
security
users
Vhost.xml 2nd
arranging
workspace
for Living Emoticon
array of objects
arrays
associative arrays
declaring
assigning
event handlers
associative arrays
authenticating
users 2nd 3rd 4th 5th 6th
with Remoting 2nd 3rd 4th 5th 6th 7th 8th 9th
users with Remoting
building ColdFusion scripts 2nd 3rd 4th
authentication
virtual classrooms
authoring environment
Flash MX 2nd
avoiding
spaghetti code
in ActionScript
AVPresence Communication component 2nd
streams
testing 2nd 3rd 4th 5th
troubleshooting

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

bandwidth
bandwidth, setting 2nd
Modem setting
bit rate
bits per second (bps)
bps (bits per second)
broadcast messages
functions for
broadcasting messages
browsers
testing in 2nd
buttons
Ping
Remove
Update
View Detail

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

calling
application instances
from SSAS 2nd 3rd 4th 5th
Flash Communication Server and establishing connections with Macromedia Flash MX 2nd 3rd 4th
functions 2nd 3rd 4th 5th 6th 7th
over NetConnections
remote functions over NetConnection 2nd 3rd
Camera object 2nd
capturing desktops as video sources 2nd
displaying 2nd 3rd 4th
camera objects
publishing live stream 2nd 3rd 4th 5th 6th 7th 8th 9th 10th
Camera.get() function
cameras
enabling
pausing
Capacity Packs 2nd
capturing
desktops as video sources
Camera object 2nd
case sensitivity
SASS
case studies
virtual classrooms
student users 2nd
teacher users 2nd
chaining
servers
Stream 2nd 3rd
Change
code values
changeClip function
creating
changing
users
names and passwords;Administration Users panel
Chat component
testing
Chat Room interface
building 2nd 3rd 4th 5th 6th 7th
chat tools
remote SharedObject
Chat UI component
Chat window
choosing
components
of interfaces 2nd 3rd
class files
adding NetDebug class files 2nd
classes
Client objects
extending 2nd
overwriting 2nd
UI components
extending 2nd
Clear
code values
clearInterval function
Client instances
customizing methods and properties 2nd
Client object
classes
extending 2nd
OOP 2nd
Client objects
permissions 2nd 3rd
security 2nd 3rd
SSAS 2nd
client user interfaces
Live Support Lobby 2nd 3rd 4th 5th
client-side ActionScript
Live Support Lobby
building client user interfaces 2nd 3rd 4th 5th
representative user interfaces 2nd
SharedObject
client/server roles
ActionScript 2nd
clip_init()
Close() method
NetStream
code
debugging
with View Line Numbers
line numbering
Living Emoticon
ActionScript 2nd 3rd 4th 5th 6th 7th 8th 9th 10th
server-side ActionScript
placing in ActionScript
spaghetti code
avoiding
synchronization 2nd
verifying
in App Inspector
virtual classrooms
authentication
building initialization scripts 2nd 3rd 4th 5th
building server scripts 2nd 3rd 4th
building student scripts 2nd 3rd 4th 5th 6th
building teacher scripts 2nd 3rd 4th 5th 6th
messaging 2nd 3rd
SharedObjects 2nd
streams 2nd
code hints
ActionScript Editor
SSAS
suffixes for 2nd
troubleshooting
code. [See also ActionScript]
codecs
Sorenson
coding
Lobby applications 2nd
call to Lobby
call to Room
initialization 2nd 3rd 4th 5th 6th 7th
server-side ActionScript 2nd
coding strategies
in ActionScript
client/server roles 2nd
data storage 2nd 3rd
timelines 2nd
ColdFusion
consuming components as web services in Flash Communication Server MX 2nd 3rd 4th 5th 6th
ColdFusion MX
SSAS
ColdFusion scripts
creating 2nd 3rd 4th
collaborative relationships
synchronization
colors
customized
in text messaging
selecting
in text messaging 2nd
commands
Debug Movie
UPDATE
SQL
commenting
in ActionScript 2nd
Communication App Inspector 2nd
Communication App Inspector. [See also App Inspector]
communication components
Communication Dictionary
Communication object library
Communication Objects 2nd
Camera 2nd
capturing desktops as video sources 2nd
displaying 2nd 3rd 4th
Microphone 2nd
NetConnection 2nd
calling remote functions 2nd 3rd
onStatus event 2nd
URI 2nd
NetServices (Flash Remoting MX) 2nd 3rd
NetStream 2nd
messaging
onStatus events
PlayLists
publishing streams 2nd 3rd
subscribing to streams 2nd
RecordSet (Flash Remoting MX) 2nd 3rd 4th 5th
SharedObject
local SharedObject 2nd
remote SharedObject 2nd
System object
Settings panel 2nd
system capabilities 2nd
Video object
Communication Objects. [See also objects]
Communication Server
initial running of application
running of application
communications book
LocalConnection
SharedObject
components
accessing object prototypes 2nd 3rd 4th 5th
AVPresence Communication 2nd
streams
testing 2nd 3rd 4th 5th
troubleshooting
Chat
testing
Communication App Inspector 2nd
ConnectionLight 2nd 3rd
NetConnection Debugger 2nd
of interfaces
choosing 2nd 3rd
PeopleList 2nd
Remoting
RoomList 2nd 3rd
accessing object prototypes 2nd 3rd 4th 5th
extending
features
overwriting 2nd
scriptLib folder 2nd
server-side
SetBandwidth 2nd 3rd
SimpleConnect 2nd 3rd 4th
connecting with
UI Components 2nd 3rd
UI components
UI Components
installing manually
UI components. [See UI components]2nd [See UI components]
UserColor 2nd 3rd
Components library
compressing
video
with Sorenson Squeeze 2nd 3rd 4th 5th 6th 7th 8th 9th
Conf folder
connect()
connect() method
connect.rejected status messages
connect.success status messages
connecting
confirming connections 2nd 3rd
ConnectionLight component 2nd 3rd
defining applications on the server 2nd 3rd
determining domain names 2nd
multiple users 2nd 3rd 4th 5th
PeopleList component 2nd
SharedObjects
to Netconnection 2nd 3rd
SimpleConnect component 2nd 3rd 4th 5th
testing 2nd
on Mac OS 2nd 3rd 4th 5th
remote testing 2nd 3rd 4th 5th
troubleshooting 2nd 3rd 4th
UI components
with ActionScript 2nd 3rd 4th 5th 6th 7th 8th 9th 10th 11th
user interfaces, building 2nd
viewing users logged into the server 2nd
connection failures 2nd 3rd 4th
connection requests
onConnect
Live Support Lobby 2nd 3rd 4th 5th
ConnectionLight component 2nd 3rd
connections
establishing
with Flash MX 2nd 3rd 4th
nonpersistent connections
persistent connections
troubleshooting
consuming
ColdFusion Components
as web services in Flash Communication Server MX 2nd 3rd 4th 5th 6th
contents
of frames
viewing
controller applications 2nd
ActionScript 2nd 3rd
interfaces 2nd 3rd 4th
main.asc
subscriber actionScript 2nd 3rd
user case studies
controller interfaces
Flash MX interfaces 2nd 3rd
controller scripts 2nd 3rd 4th
converting
QuickTime video
into Flash Video files 2nd 3rd 4th 5th 6th 7th
Count function
CPUMonitor
cropping
video
CU- [See Me]
cursors
shared cursor 2nd
customizing
methods and properties
with Client instances 2nd

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

data management
slots 2nd 3rd 4th 5th 6th 7th
data storage
ActionScript 2nd 3rd
database files
database servers
Debug Movie command
debugger
enabling
debuggers
Flash MX Debugger
NetConnection Debugger 2nd 3rd 4th 5th
debuggin
ActionScript interpreter 2nd 3rd 4th
debugging
debugging
code
View Line Numbers
debugging
Flash MX Debugger 2nd 3rd
NetConnection Debugger 2nd
SSAS 2nd 3rd
trace actions 2nd
declaring
arrays
default server administration users
defining applications on the server 2nd 3rd
Delete
code values
Deny node
development environment
authoring environment 2nd
file structure
flashcomm applications folder 2nd 3rd 4th 5th 6th
server configuration folder 2nd 3rd
servers 2nd
testing environment 2nd 3rd 4th
in browsers 2nd
in Flash MX
Development option (installation)
Diagnostic panel
Administration Console 2nd
dictionaries
Communication Dictionary
Object Dictionary
UI Component Dictionary
disconnections
onDisconnect
Live Support Lobby 2nd 3rd
displaying
Camera object 2nd 3rd 4th
domain names
determining 2nd
downloading
Remoting components
dragging
dynamic video
loadMovie() versus NetStream()

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

ECMAScript-262 specification
editions
Personal
features
Professional
Capacity Packs
features 2nd
trial version
elearning
virtual classrooms. [See virtual classrooms]
emoticons
emoticons. [See also Living Emoticon]
enabling
debugger
NetServices
in Flash Communication Server
RecordSet methods
in Flash MX
event handlers
assigning
events
NetConnection
onStatus
NetStream, OnStatus
onConnect
creating
onStatus
NetConnection 2nd
NetStream
SharedObjects
onStatus
onSync
examples
of host connection strings
exercises
11.1 Calling an Application Instance from SSAS 2nd 3rd 4th 5th
11.2 Authenticating a User 2nd 3rd 4th 5th 6th
11.3 First Contact 2nd 3rd 4th 5th 6th 7th
12.1\: Displaying the Camera 2nd 3rd 4th
13.1\: Using Remoting to Authenticate a User 2nd 3rd 4th 5th 6th
13.2\: Build the ColdFusion Script 2nd 3rd 4th
13.3\: Consume the CFC as a Web Service in Flash Communication Server MX 2nd 3rd 4th 5th 6th
13.4\: Call Flash Communication Server and Establish a Connection Using Macromedia Flash MX 2nd 3rd 4th
14.1\: Creating a New Adaptor 2nd 3rd 4th 5th
14.2 Creating a New Virtual Host and Users 2nd 3rd 4th 5th 6th
16.1\: Building the Client User Interface
16.2\: Representative Login Interface 2nd 3rd 4th
16.3\: Representative Customer Selection Interface 2nd 3rd
16.4\: The Server-Side ActionScript 2nd 3rd 4th
16.5\: The Flash Interface 2nd 3rd 4th 5th 6th
16.6 The Representative Application 2nd 3rd 4th 5th 6th
18.1 Setting Up the Timeline 2nd 3rd
18.2 Constructing the Interfaces 2nd 3rd 4th 5th 6th 7th 8th 9th
18.3 Building the ActionScript 2nd 3rd 4th 5th 6th 7th 8th 9th 10th 11th 12th 13th 14th 15th 16th 17th
18.4 Building the Server-Side ActionScript (main.asc) 2nd 3rd 4th
6.1 Get Connected with ActionScript and NetConnection() 2nd 3rd 4th 5th 6th 7th 8th 9th 10th 11th
6.2\: Allow Multiple Users to Connect 2nd 3rd 4th 5th
7.1 Flash Video Compression Using Flash MX 2nd 3rd 4th 5th 6th 7th
7.2 Video Compression Using Sorenson Squeeze 2nd 3rd 4th 5th 6th 7th 8th 9th
7.3 Streaming Video from the Server 2nd 3rd 4th 5th 6th 7th 8th 9th
7.4\: Publishing a Live Stream Using the Camera and Microphone Objects 2nd 3rd 4th 5th 6th 7th 8th 9th 10th
7.5\: Playing a Live Stream 2nd 3rd 4th 5th 6th
8.1\: Using the Remote SharedObject with the Macromedia Flash Communication Server MX UI Components 2nd 3rd 4th 5th
8.2 Implementing the Remote SharedObject 2nd 3rd 4th 5th 6th 7th 8th 9th 10th 11th 12th 13th 14th 15th
9.1\: The Simple Controller Application
Step 1\: The Interfaces 2nd 3rd 4th
Step 2\: Controller ActionScript 2nd 3rd
Step 3\: Subscriber ActionScript 2nd 3rd
9.2 The Flash MX Interface 2nd
Step 1\: Prepare the Timeline 2nd 3rd
Step 2\: The Login Interface (Frame\: 1) 2nd
Step 3\: The Subscriber Interface (Frame\: 10) 2nd 3rd 4th
Step 4\: The Controller Interface (Frame\: 20) 2nd 3rd
9.3\: Scripting
Step 1\: Initialization (Frame 1) 2nd 3rd 4th 5th 6th 7th
Step 2\: Subscriber Scripts (Frame 10) 2nd 3rd 4th
Step 3\: Controller Scripts (Frame 20) 2nd 3rd 4th
Step 4\: main.asc Scripts 2nd 3rd
Expert mode
ActionScript Editor 2nd
extending
classes
Client objects 2nd
UI component classes 2nd

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

file formats
video file formats
file structure
adaptors
applications
editing
flashcomm applications folder 2nd 3rd 4th 5th 6th
server configuration folder 2nd 3rd
virtual hosts
files
Adaptor.xml
Application.xml 2nd
database files
FLA
Flash Video (FLV)
FLV
FSO
IDX
main.asc
SSAS 2nd
presentaiton files
presentation files 2nd
SWF
recorded stream
Server.xml 2nd 3rd 4th
SWF
Vhost.xml 2nd
FLA files
Flash
displaying video
Spark comopressor
interfaces
Live Support Session 2nd 3rd 4th 5th 6th
Flash Communication Server
NetServices
enabling
versus web servers
Flash interfaces
building for remote SharedObjects 2nd 3rd
Flash MX
as authoring environment 2nd
authoring environment
enabling RecordSet methods
establishing connections 2nd 3rd 4th
file formats
interfaces 2nd
controller interfaces 2nd 3rd
login interfaces 2nd
preparing timelines 2nd 3rd
subscriber interfaces 2nd 3rd 4th
loadMovie() method
NetServices
Remoting
privacy window
testing in
tools
user interfaces
building 2nd
Flash MX authoring environment
Flash MX Debugger 2nd 3rd 4th
Flash MX debugger
Flash player
Flash player client
Flash Remoting 2nd
Flash Remoting MX
NetServices 2nd 3rd
RecordSet objects 2nd 3rd 4th 5th
Flash Remoting MX. [See Remoting]
Flash Video (FLV) files
Flash Video files
converting QuickTime videos 2nd 3rd 4th 5th 6th 7th
FlashComCustom.as 2nd
flashcomm applications folder 2nd 3rd 4th
FLV files
FSO files
IDX files
included files
matrix of files
flush function
FLV files
FLVCacheSize
Folder Watching utility
folders
adaptor
adaptors
Application folder
applications
Conf
flashcomm applications folder 2nd 3rd 4th 5th
matrix of files
output folders
compressing video
root
ScriptLib
server configuration folder 2nd 3rd
SharedObject
Streams
virtual hosts 2nd
formatting
ActionScript 2nd
avoiding spaghetti code
commenting 2nd
naming variables
placing code
using functions
forward slash (/)
FQHN (fully qualified host name)
frames
keyframes
viewing contents of
FSO files
full-duplex systems
fully qualified host name (FQHN)
function
startStream
functions
.send()
appLogin
calling 2nd 3rd 4th 5th 6th 7th
over NetConnections
Camera.get()
changeClip
creating
clearInterval
Count
flush
getProperty
in ActionScript
init_Streams()
init_Student()
initSharedObject() 2nd
initSO()
onPress
creating
onRelease
creating
onStatus 2nd
plaly()
play()
Result
service
SharedObject_init()
startPublish() 2nd
stopPublish() 2nd

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

getProperty 2nd
getProperty method
SSAS

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

half-duplex systems
handlers
onSync
SharedObjects 2nd
history
of streaming 2nd 3rd
host connection strings
examples
HTTP protocols

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

IDX files
images
importing to libraries 2nd 3rd 4th
implementing
remote SharedObjects 2nd 3rd
building Flash interfaces 2nd 3rd
calling initsharedObject() function 2nd
onSync handler 2nd
refining synchronization 2nd
setting up 2nd 3rd
testing movies 2nd
writing changed values to SharedObjects 2nd 3rd
SharedObjects 2nd
importing
images
to libraries 2nd 3rd 4th
information objects
init_Streams() function
init_Student()
initialization
of Lobby applications 2nd 3rd 4th 5th 6th 7th
initialization scripts
building for virtual classrooms 2nd 3rd 4th 5th
initializing
applications
Live Suport Lobby 2nd 3rd
scripting 2nd 3rd 4th 5th 6th 7th
initSharedObject
initSharedObject function 2nd
initSO() function
installation
components
Communication App Inspector 2nd
NetConnection Debugger 2nd
UI Components 2nd 3rd
Development option
development versus production installations
pre-installation considerations 2nd
Production option 2nd
testing 2nd
instancing
applications
SSAS 2nd
interfaces
Chat Room
building 2nd 3rd 4th 5th 6th 7th
choosing components of 2nd 3rd
client user interfaces
Live Support Lobby 2nd 3rd 4th 5th
controller applications 2nd 3rd 4th
controller interfaces
Flash
Live Support Session 2nd 3rd 4th 5th 6th
Flash MX 2nd
controller interfaces 2nd 3rd
login interfaces 2nd
subscriber interfaces 2nd 3rd 4th
timelines 2nd 3rd
Lobby 2nd
building 2nd 3rd
calls to Lobby
network gaming
Lobby interfaces
Login
building 2nd 3rd 4th
representative customer selection interfaces 2nd 3rd
representative user interfaces
Live Support Lobby 2nd
room
building 2nd 3rd 4th
calls to room
Room interfaces
subscriber interfaces
user interfaces
building 2nd 3rd
virtual classrooms
login interfaces 2nd
student interfaces 2nd 3rd 4th
teacher interfaces 2nd 3rd
timelines 2nd 3rd
Internet Access
intervals
timed events
SSAS
IP addresses
adding in Windows

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

JRUN 4

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

keyframes

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

latency
leaf1_mc[property] 2nd
libraries
Communication object library
Components library
importing images to 2nd 3rd 4th
RecordSet Libraries
loading
License panel
Administration Console
licenses
scalable licenses
line numbering
listings
12.1\: Sample Usage of the RecordSet
14.1 The default Adaptor.xml document
14.2\: The default Vhost.xml file
14.3 The Application.xml configuration file
16.1\: Full listing of SSAS onAppStart
16.2\: Full listing of SSAS onConnect
16.3\: Full listing of SSAS onAppStart
16.4\: Full listing of connectionToClient
16.5\: Full Flash ActionScript for Frame 1, ActionScript layer
16.6\: Flash ActionScript listing for representative interface
16.7\: SSAS listing for the Live Support Session application
16.8\: Full ActionScript of Client_Support_App.fla
16.9\: Final ActionScript for Representative_Support_App.fla
6.1 Final Flash ActionScript\: Step2-MultiConnect.fla
7.1\: ActionScript for videoStream.fla
7.2\: The complete ActionScript code to connect a stream
7.3\: Final ActionScript listing for PublishCam.fla
7.4\: Updated code listing for PublishCam.fla
8.1 Completed ActionScript Listing for WhiteCursor.fla
8.2 The Existing ActionScript for ShareClip.fla
8.3 Handling the onSync Event
live chats
sharing text data
Live Log panel 2nd
Administration Console
Live Support Lobby
client-side ActionScript
building client user interfaces 2nd 3rd 4th 5th
representative user interfaces 2nd
SSAS 2nd
creating unique application instances 2nd 3rd
handling connection requests (onConnect) 2nd 3rd 4th 5th
handling user disconnections (onDisconnect) 2nd 3rd
initializing applications 2nd 3rd
Live Support Session
Flash interface 2nd 3rd 4th 5th 6th
represenative application 2nd 3rd 4th 5th 6th
SSAS 2nd 3rd 4th
live video
playing 2nd 3rd 4th 5th 6th 7th 8th
publishing with camera and microphone objects 2nd 3rd 4th 5th 6th 7th 8th 9th 10th
live video switchering 2nd 3rd
Living Emoticon 2nd
code
ActionScript 2nd 3rd 4th 5th 6th 7th 8th 9th 10th
server-side ActionScript
images
importing to libraries 2nd 3rd 4th
interfaces
choosing components 2nd 3rd
user access
workspace
arranging
Living Emoticon. [See also emoticons]
loading
applications
with App Inspector 2nd 3rd 4th
RecordSet Libraries
LoadMovie()
versus NetStream
loadMovie() method
loadMovie() object
Lobby applications 2nd
call to Lobby
call to Room
coding 2nd
developing 2nd 3rd
initialization 2nd 3rd 4th 5th 6th 7th
RoomList UI component 2nd 3rd 4th
server-side ActionScript 2nd
Lobby interface
building 2nd 3rd
Lobby interfaces 2nd
calls to Lobby
network gaming
local SharedObject 2nd
local SharedObjects
LocalConnection
localConnection() object
locking
SharedObjects
SSAS
logging
into Administration Console 2nd 3rd 4th
logging in
Login interface
building 2nd 3rd 4th
login interfaces
Flash MX interfaces 2nd
virtual classrooms 2nd
loops
Lurker mode

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

Mac OS
testing connections 2nd 3rd 4th 5th
Macromedia ColdFusion MX
Macromedia Flash Communication Server. [See Flash Communication Server]
Macromedia Flash MX. [See Flash MX]
Macromedia J2EE Server products
Macromedia SWF security 2nd
main.asc
server scripts
virtual classrooms 2nd 3rd 4th
SSAS 2nd 3rd
main.asc file
SSAS 2nd
Maintenance panel
Administration Console
applications
servers
virtual hosts
MBONE (multi-casting backbone)
messages
broadcast messages
functions for
broadcasting
connect.rejected
connect.success
Success messages
messaging
NetStream
virtual classrooms 2nd 3rd
methods
.clear
.connect
.flush
.purge
.send
acceptConnection()
appLogin
connect() 2nd
customizing with Client instances 2nd
getProperty
loadMovie()
NetConnection 2nd
NetStream
Close()
NetStream() 2nd
onAppStart
overwriting
onConnect
play()
publish() 2nd
record()
RecordSet methods
enabling in Flash MX
rejectConnection()
setProperty
SharedObjects
.close()
.connect()
.flush()
.getSize()
.send()
.setFPS()
SharedObject.getLocal()
SharedObject.getRemote()
SSAS 2nd
SSAS 2nd 3rd
startDrag()
swapDepths()
Microphone object 2nd
microphone objects
publishing live stream 2nd 3rd 4th 5th 6th 7th 8th 9th 10th
microphones
enabling
muting 2nd
Microsoft .NET
modes
Lurker mode
monitors
Shared Objects 2nd
Streams
multi-casting backbone (MBONE)

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

name values
synchronization
names
changing
in Administration Users panel
naming
variables
in ActionScript
NetConnection
calling functions
connecting
SharedObjects 2nd 3rd
events
onStatus
methods 2nd
properties 2nd
SSAS 2nd
NetConnection Debugger 2nd 3rd 4th 5th 6th 7th 8th 9th 10th
NetConnection object 2nd
calling remote functions 2nd 3rd
onStatus event 2nd
URI 2nd
NetConnection() ibhect
NetDebug class files
adding 2nd
NetServices 2nd
enabling
in Flash Communication Server
RecordSet object 2nd 3rd
SSAS
NetServices object
Flash Remoting MX 2nd 3rd
Remoting
NetStream 2nd
netstream
NetStream
Close() method
object 2nd
overview of 2nd 3rd
properties 2nd
publisher streams
roles of 2nd
streaming video 2nd 3rd
subscriber streams
versus loadMovie()
NetStream object 2nd
messaging
onStatus events
PlayLists
publishing streams 2nd 3rd
subscribing to streams 2nd
NetStream() methods 2nd
nodes
Adaptor
Allow
Deny
Order
Server
VirtualHost
nonpersistent connections
Normal mode
ActionScript Editor
numbering
lines

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

Object Dictionary
object prototypes
accessing 2nd 3rd 4th 5th
objects
data management using slots 2nd 3rd 4th
loadMovie()
localConnection()
NetConnection()
NetStream 2nd
netstream(). [See netstream]
presentationSWF
RecordSet objects
NetServices 2nd 3rd
server-side objects (SSAS)
Application 2nd
Client 2nd
NetConnection 2nd
NetServices
RecordSet
SharedObject. [See SharedObject]
Stream 2nd 3rd
objects. [See also Communication Objects]
oldValue
synchronization
onAppStart method
overwriting
onConnect
handling connection requests
Live Support Lobby 2nd 3rd 4th 5th
onConnect events
creating
onConnect method
onDisconnect
handling disconnections
Live Support Lobby 2nd 3rd
onPress function
creating
onRelease function
creating
onStatus
NetConnection events
OnStatus
NetStream events
onStatus
SharedObjects events
triggering
onStatus event
NetConnection object 2nd
onStatus events
NetStream
onStatus function 2nd
onStatus handler
onSync 2nd
SharedObjects events
onSync handler
SharedObjects 2nd
OOP
Client object 2nd
Order node
output folders
compressing video
Output window
overwriting
onAppStart method
prototypes
overwriting classes 2nd

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

panels
Actions
ActionScript
Administration Users
Application Instances 2nd
Diagnostic
License
Live Log 2nd 3rd
Maintenance
Settings
System object 2nd
Statistics Monitor 2nd 3rd
passwords
changing
in Administration Users panel
PeopleList component 2nd
permissions
Client objects 2nd 3rd
persistent connections
Personal edition
Personal Edition
features
Ping button
Diagnostic panel
placing
code
in ActionScript
plaly() function
play() function
play() method
playing
live video 2nd 3rd 4th 5th 6th 7th 8th
pre-recorded video 2nd
playing. [See also streaming]
PlayLists
NetStream
ports
Admin port
Server port
pre-recorded video
playing 2nd
PresentationSWF 2nd
presentationSWF object
privacy window
Production option (installation) 2nd
Professional edition
Professional Edition
Capacity Packs
features 2nd
Professional edition
trial version
Progressive Networks
projects
testing 2nd 3rd
properties
customizing
with Client instances 2nd
data management using slots 2nd 3rd 4th
NetConnection 2nd
NetStream 2nd
SharedObjects
.data
weight 2nd 3rd
protocols
HTTP
ports
Real Time Streaming Protocol
RTMP 2nd 3rd 4th
prototypes
overwriting
proxy SharedObjects
SSAS 2nd 3rd
publish() method 2nd
publisher streams
publishing
live video
with camera and microphone objects 2nd 3rd 4th 5th 6th 7th 8th 9th 10th
streams
NetStream 2nd 3rd

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

QuickTime 2nd
converting videos into Flash Video files 2nd 3rd 4th 5th 6th 7th

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

Real Networks
Real Player
Real Time Messaging Protocol (RTMP)
Real Time Messaging Protocol. [See RTMP]
Real Time Streaming Protocol
receiver streams
record() method
recorded stream files
recording
video
Stream
RecordSet
SSAS
RecordSet Class Files
RecordSet Libraries
loading
RecordSet object
Flash Remoting MX 2nd 3rd 4th 5th
RecordSet objects
NetServices 2nd 3rd
refining
synchronization
remote SharedObjects 2nd
Reflector
registering
adaptors
Reject
code values
rejectConnection()
Reload App
remote functions
calling over NetConnection 2nd 3rd
remote SharedObject 2nd 3rd
chat tools
using with Macromedia Flash Communication Server MX UI components 2nd 3rd 4th 5th
remote SharedObjects
building Flash interfaces 2nd 3rd
building onSync handler 2nd
calling initsharedObject() function 2nd
implementing 2nd 3rd
refining synchronization 2nd
setting up 2nd 3rd
suggestions for using
testing movies 2nd
writing changed values to SharedObjects 2nd 3rd
remote testing 2nd 3rd 4th 5th
Remoting 2nd
AMF
Application Servers 2nd
authenticating users 2nd 3rd 4th 5th 6th 7th 8th 9th
building ColdFusion scripts 2nd 3rd 4th
components
NetServices
Flash Communication Server
Flash MX
NetServices objects
Remove button
removing
virtual host users
represenative application
Live Support Session 2nd 3rd 4th 5th 6th
representative customer selection interfaces 2nd 3rd
representative user interfaces
Live Support Lobby 2nd
ResourceLimits
resources for more information about Flash Communication Server
Result function
roles
of NetStream 2nd
Room interfaces
room interfaces
building 2nd 3rd 4th
calls to room
RoomList UI component 2nd 3rd
accessing object prototypes 2nd 3rd 4th 5th
extending
features
overwriting 2nd
root folders
root users
RTMP (Real Time Messaging Protocol)
RTMP (Real Time Messaging Protocol) protocol
RTMP protocol 2nd 3rd
RTMP protocols

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

scalable licenses
screens
Administration Console
Script Lib folder
scripting
controller scripts 2nd 3rd 4th
FlashComCustom.as 2nd
initializing 2nd 3rd 4th 5th 6th 7th
main.asc 2nd 3rd
subscriber scripts 2nd 3rd 4th
ScriptLib folder
components 2nd
scripts
ColdFusion scripts
creating 2nd 3rd 4th
security 2nd 3rd 4th
access security 2nd
adaptors
applications
Client objects 2nd 3rd
SharedObject
SSAS
SWF movies 2nd
transmission security 2nd
virtual hosts
sender streams
server administrators
server configuration folder 2nd 3rd
Server Management ActionScript Dictionary
Server node
Server port
server scripts
building in virtual classrooms 2nd 3rd 4th
server strings
server users
adding
server-side (ASC) files
changes to
server-side ActionScript 2nd 3rd 4th
code for Living Emoticon
Server-Side ActionScript (SSAS) 2nd
server-side ActionScript. [See SSAS]2nd [See SSAS]
server-side components
Server-Side JavaScript 1.5. [See SSJS]
server-side objects
SSAS
Application 2nd
Client 2nd
NetConnection 2nd
NetServices
RecordSet
SharedObject. [See SharedObject]
Stream 2nd 3rd
Server.xml 2nd 3rd 4th
serverRet()
servers
accessing 2nd
application servers
architecture of Flash Communication Server 2nd 3rd 4th
security 2nd
Server.xml 2nd 3rd 4th
users 2nd
chaining (Stream) 2nd 3rd
database servers
Maintenance panel
Administration Console
streaming video from 2nd 3rd 4th 5th 6th 7th 8th 9th
web
accessing
web servers
service function
SetBandwidth component 2nd 3rd
setInterval
setProperty method
SSAS
setting up
remote SharedObjects 2nd 3rd
Settings panel
System object 2nd
shared cursor 2nd
Shared Objects Monitor 2nd
SharedObject 2nd 3rd
client-side ActionScript
local SharedObject 2nd
remote SharedObject 2nd 3rd
shared cursor 2nd
SSAS 2nd
locking
methods 2nd
proxied SharedObjects 2nd 3rd
security
slots 2nd 3rd
synchronization 2nd 3rd
SharedObject folder
SharedObject.getLocal()
SharedObjects methods
SharedObject.getRemote()
SharedObjects methods
SharedObject_init() function
SharedObjects 2nd
connecting
to NetConnection 2nd 3rd
data management
slots 2nd 3rd 4th 5th 6th 7th
events
onStatus
onSync
implementing 2nd
local SharedObjects
methods
.close()
.connect()
.flush()
.getSize()
.send()
.setFPS()
ShareObject.getLocal()
ShareObject.Remote
properties
.data
remote SharedObjects
virtual classrooms 2nd
sharing
text data
SimpleConnect
connecting UI components
SimpleConnect component 2nd 3rd 4th
connecting with
skinning
UI components 2nd
slots
for data management 2nd 3rd
object, properties, and values 2nd 3rd 4th
SharedObject
SSAS 2nd 3rd
SMIL (Synchronized Multimedia Interface Language)
Sorenson
Sorenson Spark 2nd
converting QuickTime video into Flash Video files 2nd 3rd 4th 5th 6th 7th
Sorenson Spark audio/video compressor
Sorenson Spark Pro codec
Sorenson Squeeze
video compression 2nd 3rd 4th 5th 6th 7th 8th 9th
spaghetti code
avoiding
speakerStream
SQL
UPDATE command
SSAS
application instances 2nd
calling application instances 2nd 3rd 4th 5th
case sensitive
code hints
ColdFusion MX
debugging techniques 2nd 3rd
Live Support Lobby 2nd
creating unique application instances 2nd 3rd
handling connection requests (onConnect) 2nd 3rd 4th 5th
handling user disconnections (onDisconnect) 2nd 3rd
initializing applications 2nd 3rd
Live Support Session 2nd 3rd 4th
main.asc 2nd 3rd
main.asc file 2nd
methods 2nd 3rd
server-side objects
Application 2nd
Client 2nd
NetConnection 2nd
NetServices
RecordSet
SharedObject. [See SharedObject]
Stream 2nd 3rd
SharedObject
locking
methods 2nd
proxies 2nd 3rd
security
slots 2nd 3rd
synchronization 2nd 3rd
timed events using intervals
SSAS (Server-Side ActionScript) 2nd
SSAS (server-side ActionScript) 2nd
SSJS (Server-Side JavaScript 1.5)
startDrag() method
startPublish() function 2nd
startStream function
Statistics Monitor panel
App Inspector 2nd 3rd
stopping
virtual hosts
stopPublish()
stopPublish() function
Stream
live video switcher 2nd 3rd
servers
chaining 2nd 3rd
video recorders
Stream objects
SSAS 2nd 3rd
streaming
history of 2nd 3rd
live video 2nd 3rd
video 2nd 3rd
from servers 2nd 3rd 4th 5th 6th 7th 8th 9th
streaming. [See also playing]
streams
publisher streams
publishing with NetStream 2nd 3rd
subscriber streams 2nd
subscribing to with NetStream 2nd
virtual classrooms 2nd
Streams folder
Streams Monitor 2nd
student interfaces
virtual classrooms 2nd 3rd 4th
student scripts
building in virtual classrooms 2nd 3rd 4th 5th 6th
student_source
studentStream
styling
ActionScript 2nd
avoiding spaghetti code
commenting 2nd
naming variables
placing code
using functions
subscriber applications
user case studies
subscriber interfaces
Flash MX interfaces 2nd 3rd 4th
subscriber scripts 2nd 3rd 4th
subscriber streams 2nd
subscriber/publisher relationships
synchronization
subscribing
to streams
NetStream 2nd
Success
code values
Success messages
suffixes
_pso
for code hints 2nd
Sun J2EE
swapDepths() method
SWF
movies
security 2nd
PresentationSWF 2nd
presentationSWF
SWF files
switching
live video 2nd 3rd
synchronization 2nd
.onSync method
code 2nd
collaborative relationships
name value
oldValue
refining
in remote SharedObjects 2nd
SharedObject
SSAS 2nd 3rd
subscriber/publisher relationships
Synchronized Multimedia Interface Language (SMIL)
system capabilities
System object 2nd
System object
Settings panel 2nd
system capabilities 2nd

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

teacher interfaces
virtual classrooms 2nd 3rd
teacher scripts
building in virtual classrooms 2nd 3rd 4th 5th 6th
technical support applications 2nd
Live Support Lobby. [See Live Support Lobby]
Live Support Session. [See Live Support Session]
Test ActionScript feature
testing
applications
connections 2nd
on Mac OS 2nd 3rd 4th 5th
remote testing 2nd 3rd 4th 5th
troubleshooting 2nd 3rd 4th
movies
remote SharedObjects 2nd
projects 2nd 3rd
testing environment 2nd 3rd 4th
in browsers 2nd
in Flash MX
text data
sharing
text messaging
colors, selecting 2nd
customized colors
testing
ThreadPoolGC
timed events
SSAS
intervals
timelines
ActionScript 2nd
interfaces
virtual classrooms 2nd 3rd
preparing for Flash MX interfaces 2nd 3rd
trace actions
debugging 2nd
trace output
of clients connecting to sessions that have already moved pieces around
transmission security 2nd
triggering
onStatus
troubleshooting
applications 2nd 3rd
code hints
connections
onStatus
with NetConnection Debugger

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

UI Component Dictionary
UI Components 2nd 3rd
UI components 2nd 3rd 4th
Chat UI component
communication components
communication components ActionScript objects 2nd 3rd
connecting
with ActionScript 2nd 3rd 4th 5th 6th 7th 8th 9th 10th 11th
connecting to SimpleConnect
extending classes 2nd
UI Components
installing manually
UI components
Lurker mode
skinning 2nd
using remote SharedObject 2nd 3rd 4th 5th
UI components. [See components]
Uniform Resource Identifier. [See URI]2nd [See URI]
unique application instances
creating 2nd 3rd
Update button
Diagnostic panel
UPDATE command
SQL
upgrades
Capacity Packs
URI
absolute URI
URI (Uniform Resource Identifier) 2nd
user case studies
controller applications
subscriber applications
user interfaces
building 2nd 3rd 4th 5th
UserColor component 2nd 3rd
users
access
to Living Emoticon
authenticating 2nd 3rd 4th 5th 6th
with Remoting 2nd 3rd 4th 5th 6th 7th 8th 9th
authenticating with Remoting
building with ColdFusion scripts 2nd 3rd 4th
connecting multiple users 2nd 3rd 4th 5th
creating 2nd 3rd 4th 5th 6th
giving access to adaptors and virtual hosts
of servers 2nd
server users
adding
student user case studies
virtual classrooms 2nd
teacher user case studies
virtual classrooms 2nd
virtual host users. [See virtual host users]
virtual hosts
utilities
Folder Watching

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

values
data management
using slots 2nd 3rd 4th
variables
naming in ActionScript
verifying
code
in App Inspector
Vhost.xml 2nd
video 2nd
bandwidth, setting 2nd
Modem setting
compressing
with Sorenson Squeeze 2nd 3rd 4th 5th 6th 7th 8th 9th
cropping
file formats
live video switcher 2nd 3rd
pausing
playing live video 2nd 3rd 4th 5th 6th 7th 8th
playing pre-recorded video 2nd
recorders
Stream
streaming 2nd 3rd
from servers 2nd 3rd 4th 5th 6th 7th 8th 9th
streams
testing 2nd 3rd 4th 5th
troubleshooting
video converencing
Video object
video sources
capturing desktops
Camera object 2nd
View Detail button
View Line Numbers
viewing
frame contents
viewing users logged into the server 2nd
Virtual Classrooms
virtual classrooms
case studies
student users 2nd
teacher users 2nd
code
authentication
building initialization scripts 2nd 3rd 4th 5th
messaging 2nd 3rd
server scripts 2nd 3rd 4th
SharedObjects 2nd
streams 2nd
student scripts 2nd 3rd 4th 5th 6th
teacher scripts 2nd 3rd 4th 5th 6th
interfaces
login interfaces 2nd
student interfaces 2nd 3rd 4th
teacher interfaces 2nd 3rd
timelines 2nd 3rd
virtual host administration
virtual host administrators
virtual host users
adding
removing
virtual hosts 2nd
adding virtual host users
architecture of Flash Communication Server
folders 2nd
security
users
Vhost.xml 2nd
creating 2nd 3rd 4th 5th 6th
giving users access
Maintenance panel
removing virtual host users
stopping
VirtualHost node

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

web servers
accessing
versus Flash Communication Server
web services
consuming ColdFusion Components as web services in Flash Communication Server MX 2nd 3rd 4th 5th 6th
weight property 2nd 3rd
Whiteboard
Windows
adding IP addresses
windows
Chat
Output
workspace
arranging
for Living Emoticon
writing
changed values
to SharedObjects 2nd 3rd

[ Team LiB ]


[ Team LiB ]

[SYMBOL] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X]

XML

[ Team LiB ]


Team LiB

Brought to You by